diff options
Diffstat (limited to 'src/cgeo/geocaching/cgeodetail.java')
| -rw-r--r-- | src/cgeo/geocaching/cgeodetail.java | 1902 |
1 files changed, 1902 insertions, 0 deletions
diff --git a/src/cgeo/geocaching/cgeodetail.java b/src/cgeo/geocaching/cgeodetail.java new file mode 100644 index 0000000..a786cb3 --- /dev/null +++ b/src/cgeo/geocaching/cgeodetail.java @@ -0,0 +1,1902 @@ +package cgeo.geocaching; + +import gnu.android.app.appmanualclient.*; + +import java.util.ArrayList; +import java.util.HashMap; +import android.os.Handler; +import android.os.Message; +import android.os.Bundle; +import android.util.Log; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.ContentValues; +import android.content.Context; +import android.text.Html; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.method.LinkMovementMethod; +import android.view.ContextMenu; +import android.view.View; +import android.view.Menu; +import android.view.MenuItem; +import android.view.LayoutInflater; +import android.widget.ScrollView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.ImageView; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.database.Cursor; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Build; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.SubMenu; +import android.view.WindowManager; +import android.widget.Button; + +import com.google.android.apps.analytics.GoogleAnalyticsTracker; +import java.net.URLEncoder; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.Locale; +import java.util.Map.Entry; + +public class cgeodetail extends Activity { + public Long searchId = null; + public cgCache cache = null; + public String geocode = null; + public String name = null; + public String guid = null; + private GoogleAnalyticsTracker tracker = null; + private Resources res = null; + private Activity activity = null; + private LayoutInflater inflater = null; + private cgeoapplication app = null; + private cgSettings settings = null; + private cgBase base = null; + private cgWarning warning = null; + private cgGeo geo = null; + private cgUpdateLoc geoUpdate = new update(); + private float pixelRatio = 1; + private TextView cacheDistance = null; + private String contextMenuUser = null; + private ProgressDialog waitDialog = null; + private ProgressDialog descDialog = null; + private Spanned longDesc = null; + private Boolean longDescDisplayed = false; + private loadCache threadCache = null; + private loadLongDesc threadLongDesc = null; + private Thread storeThread = null; + private Thread refreshThread = null; + private HashMap<String, Integer> gcIcons = new HashMap<String, Integer>(); + private ProgressDialog storeDialog = null; + private ProgressDialog refreshDialog = null; + private ProgressDialog dropDialog = null; + private HashMap<Integer, String> calendars = new HashMap<Integer, String>(); + private Handler storeCacheHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + storeThread = null; + + try { + cache = app.getCache(searchId); // reload cache details + } catch (Exception e) { + warning.showToast(res.getString(R.string.err_store_failed)); + + Log.e(cgSettings.tag, "cgeodetail.storeCacheHandler: " + e.toString()); + } + + setView(); + } + }; + + private Handler refreshCacheHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + refreshThread = null; + + try { + cache = app.getCache(searchId); // reload cache details + } catch (Exception e) { + warning.showToast(res.getString(R.string.err_refresh_failed)); + + Log.e(cgSettings.tag, "cgeodetail.refreshCacheHandler: " + e.toString()); + } + + setView(); + } + }; + + private Handler dropCacheHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + try { + cache = app.getCache(searchId); // reload cache details + } catch (Exception e) { + warning.showToast(res.getString(R.string.err_drop_failed)); + + Log.e(cgSettings.tag, "cgeodetail.dropCacheHandler: " + e.toString()); + } + + setView(); + } + }; + + private Handler loadCacheHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (searchId == null || searchId <= 0) { + warning.showToast(res.getString(R.string.err_dwld_details_failed)); + + finish(); + return; + } + + if (app.getError(searchId) != null) { + warning.showToast(res.getString(R.string.err_dwld_details_failed_reason) + " " + app.getError(searchId) + "."); + + finish(); + return; + } + + setView(); + + if (settings.autoLoadDesc == 1) { + try { + loadLongDesc(); + } catch (Exception e) { + // activity is not visible + } + } + + (new loadMapPreview(cache, loadMapPreviewHandler)).start(); + } + }; + + final Handler loadMapPreviewHandler = new Handler() { + @Override + public void handleMessage(Message message) { + BitmapDrawable image = (BitmapDrawable) message.obj; + ScrollView scroll = (ScrollView) findViewById(R.id.details_list_box); + ImageView view = (ImageView) findViewById(R.id.map_preview); + + if (image != null && view != null) { + view.setImageDrawable(image); + + if (scroll.getScrollY() == 0) { + scroll.scrollTo(0, (int) (80 * pixelRatio)); + } + view.setVisibility(View.VISIBLE); + } + } + }; + + private Handler loadDescriptionHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (longDesc == null && cache != null && cache.description != null) { + longDesc = Html.fromHtml(cache.description.trim(), new cgHtmlImg(activity, settings, geocode, true, cache.reason, false), null); + } + + if (longDesc != null) { + ((LinearLayout) findViewById(R.id.desc_box)).setVisibility(View.VISIBLE); + TextView descView = (TextView) findViewById(R.id.description); + if (cache.description.length() > 0) { + descView.setVisibility(View.VISIBLE); + descView.setText(longDesc, TextView.BufferType.SPANNABLE); + descView.setMovementMethod(LinkMovementMethod.getInstance()); + } + else { + descView.setVisibility(View.GONE); + } + + Button showDesc = (Button) findViewById(R.id.show_description); + showDesc.setVisibility(View.GONE); + showDesc.setOnTouchListener(null); + showDesc.setOnClickListener(null); + } else { + warning.showToast(res.getString(R.string.err_load_descr_failed)); + } + + if (descDialog != null && descDialog.isShowing()) { + descDialog.dismiss(); + } + + longDescDisplayed = true; + } + }; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // init + activity = this; + res = this.getResources(); + app = (cgeoapplication) this.getApplication(); + settings = new cgSettings(this, getSharedPreferences(cgSettings.preferences, 0)); + base = new cgBase(app, settings, getSharedPreferences(cgSettings.preferences, 0)); + warning = new cgWarning(this); + + // set layout + if (settings.skin == 1) { + setTheme(R.style.light); + } else { + setTheme(R.style.dark); + } + setContentView(R.layout.detail); + base.setTitle(activity, res.getString(R.string.cache)); + + init(); + + // get parameters + final Bundle extras = getIntent().getExtras(); + final Uri uri = getIntent().getData(); + + // try to get data from extras + if (geocode == null && extras != null) { + geocode = extras.getString("geocode"); + name = extras.getString("name"); + guid = extras.getString("guid"); + } + + // try to get data from URI + if (geocode == null && guid == null && uri != null) { + String uriHost = uri.getHost().toLowerCase(); + String uriPath = uri.getPath().toLowerCase(); + String uriQuery = uri.getQuery(); + + if (uriQuery != null) { + Log.i(cgSettings.tag, "Opening URI: " + uriHost + uriPath + "?" + uriQuery); + } else { + Log.i(cgSettings.tag, "Opening URI: " + uriHost + uriPath); + } + + if (uriHost.contains("geocaching.com") == true) { + geocode = uri.getQueryParameter("wp"); + guid = uri.getQueryParameter("guid"); + + if (geocode != null && geocode.length() > 0) { + geocode = geocode.toUpperCase(); + guid = null; + } else if (guid != null && guid.length() > 0) { + geocode = null; + guid = guid.toLowerCase(); + } else { + warning.showToast(res.getString(R.string.err_detail_open)); + finish(); + return; + } + } else if (uriHost.contains("coord.info") == true) { + if (uriPath != null && uriPath.startsWith("/gc") == true) { + geocode = uriPath.substring(1).toUpperCase(); + } else { + warning.showToast(res.getString(R.string.err_detail_open)); + finish(); + return; + } + } + } + + // google analytics + tracker = GoogleAnalyticsTracker.getInstance(); + tracker.start(cgSettings.analytics, this); + tracker.dispatch(); + if (geocode != null) { + base.sendAnal(activity, tracker, "/cache/detail#" + geocode); + } + + // no given data + if (geocode == null && guid == null) { + warning.showToast(res.getString(R.string.err_detail_cache)); + finish(); + return; + } + + app.setAction(geocode); + + try { + if (name != null && name.length() > 0) { + waitDialog = ProgressDialog.show(this, name, res.getString(R.string.cache_dialog_loading_details), true); + } else if (geocode != null && geocode.length() > 0) { + waitDialog = ProgressDialog.show(this, geocode.toUpperCase(), res.getString(R.string.cache_dialog_loading_details), true); + } else { + waitDialog = ProgressDialog.show(this, res.getString(R.string.cache), res.getString(R.string.cache_dialog_loading_details), true); + } + waitDialog.setCancelable(true); + } catch (Exception e) { + // nothing, we lost the window + } + + threadCache = new loadCache(loadCacheHandler, geocode, guid); + threadCache.start(); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + setView(); + } + + @Override + public void onResume() { + super.onResume(); + + settings.load(); + + if (geo == null) { + geo = app.startGeo(activity, geoUpdate, base, settings, warning, 0, 0); + } + setView(); + } + + @Override + public void onDestroy() { + if (geo != null) { + geo = app.removeGeo(); + } + if (tracker != null) tracker.stop(); + + super.onDestroy(); + } + + @Override + public void onStop() { + if (geo != null) { + geo = app.removeGeo(); + } + + super.onStop(); + } + + @Override + public void onPause() { + if (geo != null) { + geo = app.removeGeo(); + } + + super.onPause(); + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) { + super.onCreateContextMenu(menu, view, info); + final int viewId = view.getId(); + + if (viewId == R.id.author || viewId == R.id.value) { + if (viewId == R.id.author) { // Author of a log entry + contextMenuUser = ((TextView)view).getText().toString(); + } else if (viewId == R.id.value) { // The owner of the cache + if (cache.ownerReal != null && cache.ownerReal.length() > 0) { + contextMenuUser = cache.ownerReal; + } else { + contextMenuUser = cache.owner; + } + } + + menu.setHeaderTitle(res.getString(R.string.user_menu_title) + " " + contextMenuUser); + menu.add(viewId, 1, 0, res.getString(R.string.user_menu_view_hidden)); + menu.add(viewId, 2, 0, res.getString(R.string.user_menu_view_found)); + menu.add(viewId, 3, 0, res.getString(R.string.user_menu_open_browser)); + } + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + final int group = item.getGroupId(); + + if (group == R.id.author || group == R.id.value) { + final int id = item.getItemId(); + + if (id == 1) { + final Intent cachesIntent = new Intent(activity, cgeocaches.class); + + cachesIntent.putExtra("type", "owner"); + cachesIntent.putExtra("username", contextMenuUser); + cachesIntent.putExtra("cachetype", settings.cacheType); + + activity.startActivity(cachesIntent); + + return true; + } else if (id == 2) { + final Intent cachesIntent = new Intent(activity, cgeocaches.class); + + cachesIntent.putExtra("type", "username"); + cachesIntent.putExtra("username", contextMenuUser); + cachesIntent.putExtra("cachetype", settings.cacheType); + + activity.startActivity(cachesIntent); + + return true; + } else if (id == 3) { + activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + URLEncoder.encode(contextMenuUser)))); + + return true; + } + } + return false; + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + if (cache != null && cache.latitude != null && cache.longitude != null) { + menu.add(0, 2, 0, res.getString(R.string.cache_menu_compass)).setIcon(android.R.drawable.ic_menu_compass); // compass + + SubMenu subMenu = menu.addSubMenu(1, 0, 0, res.getString(R.string.cache_menu_navigate)).setIcon(android.R.drawable.ic_menu_more); + subMenu.add(0, 8, 0, res.getString(R.string.cache_menu_radar)); // radar + if (cache != null && cache.reason >= 1 && settings.storeOfflineMaps == 1) { + subMenu.add(1, 6, 0, res.getString(R.string.cache_menu_map_static)); // static maps + } + subMenu.add(0, 1, 0, res.getString(R.string.cache_menu_map)); // c:geo map + if (base.isLocus(activity)) { + subMenu.add(0, 20, 0, res.getString(R.string.cache_menu_locus)); // ext.: locus + } + if (base.isRmaps(activity)) { + subMenu.add(0, 21, 0, res.getString(R.string.cache_menu_rmaps)); // ext.: rmaps + } + subMenu.add(0, 23, 0, res.getString(R.string.cache_menu_map_ext)); // ext.: other + subMenu.add(0, 9, 0, res.getString(R.string.cache_menu_tbt)); // turn-by-turn + } + + if (cache != null && cache.hidden != null && (cache.type.equalsIgnoreCase("event") == true || cache.type.equalsIgnoreCase("mega") == true || cache.type.equalsIgnoreCase("cito") == true)) { + menu.add(1, 11, 0, res.getString(R.string.cache_menu_event)).setIcon(android.R.drawable.ic_menu_agenda); // add event to calendar + } + if (settings.isLogin() == true) { + menu.add(1, 3, 0, res.getString(R.string.cache_menu_visit)).setIcon(android.R.drawable.ic_menu_agenda); // log visit + } + + if (cache != null && cache.spoilers != null && cache.spoilers.size() > 0) { + menu.add(1, 5, 0, res.getString(R.string.cache_menu_spoilers)).setIcon(android.R.drawable.ic_menu_gallery); // spoiler images + } + + if (cache != null && cache.latitude != null && cache.longitude != null) { + menu.add(0, 10, 0, res.getString(R.string.cache_menu_around)).setIcon(android.R.drawable.ic_menu_rotate); // caches around + } + + menu.add(1, 7, 0, res.getString(R.string.cache_menu_browser)).setIcon(android.R.drawable.ic_menu_info_details); // browser + menu.add(0, 12, 0, res.getString(R.string.cache_menu_share)).setIcon(android.R.drawable.ic_menu_share); // share cache + + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + final int menuItem = item.getItemId(); + + if (menuItem == 1) { + showOnMap(); + return true; + } else if (menuItem == 2) { + navigateTo(); + return true; + } else if (menuItem == 3) { + logVisit(); + return true; + } else if (menuItem == 5) { + showSpoilers(); + return true; + } else if (menuItem == 6) { + showSmaps(); + return true; + } else if (menuItem == 7) { + activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/seek/cache_details.aspx?wp=" + cache.geocode))); + return true; + } else if (menuItem == 8) { + radarTo(); + return true; + } else if (menuItem == 9) { + if (geo != null) { + base.runNavigation(activity, res, settings, warning, tracker, cache.latitude, cache.longitude, geo.latitudeNow, geo.longitudeNow); + } else { + base.runNavigation(activity, res, settings, warning, tracker, cache.latitude, cache.longitude); + } + + return true; + } else if (menuItem == 10) { + cachesAround(); + return true; + } else if (menuItem == 11) { + addToCalendar(); + return true; + } else if (menuItem == 12) { + shareCache(); + return true; + } else if (menuItem == 20) { + base.runExternalMap(cgBase.mapAppLocus, activity, res, warning, tracker, cache); // locus + return true; + } else if (menuItem == 21) { + base.runExternalMap(cgBase.mapAppRmaps, activity, res, warning, tracker, cache); // rmaps + return true; + } else if (menuItem == 23) { + base.runExternalMap(cgBase.mapAppAny, activity, res, warning, tracker, cache); // rmaps + return true; + } + + return false; + } + + private void init() { + final DisplayMetrics dm = getResources().getDisplayMetrics(); + pixelRatio = dm.density; + + if (inflater == null) { + inflater = activity.getLayoutInflater(); + } + if (geo == null) { + geo = app.startGeo(activity, geoUpdate, base, settings, warning, 0, 0); + } + + if (searchId != null && searchId > 0) { + cache = app.getCache(searchId); + if (cache != null && cache.geocode != null) { + geocode = cache.geocode; + } + } + + if (geocode != null && geocode.length() > 0) { + app.setAction(geocode); + } + } + + private void setView() { + RelativeLayout itemLayout; + TextView itemName; + TextView itemValue; + + if (searchId == null) { + return; + } + + cache = app.getCache(searchId); + + if (cache == null) { + if (waitDialog != null && waitDialog.isShowing()) waitDialog.dismiss(); + + if (geocode != null && geocode.length() > 0) { + warning.showToast(res.getString(R.string.err_detail_cache_find) + " " + geocode + "."); + } else { + geocode = null; + warning.showToast(res.getString(R.string.err_detail_cache_find_some)); + } + + finish(); + return; + } + + if (cache.reason >= 1) { + base.sendAnal(activity, tracker, "/cache/detail/stored"); + } else { + base.sendAnal(activity, tracker, "/cache/detail/online"); + } + + try { + if (gcIcons == null || gcIcons.isEmpty()) { + gcIcons.put("ape", R.drawable.type_ape); + gcIcons.put("cito", R.drawable.type_cito); + gcIcons.put("earth", R.drawable.type_earth); + gcIcons.put("event", R.drawable.type_event); + gcIcons.put("letterbox", R.drawable.type_letterbox); + gcIcons.put("locationless", R.drawable.type_locationless); + gcIcons.put("mega", R.drawable.type_mega); + gcIcons.put("multi", R.drawable.type_multi); + gcIcons.put("traditional", R.drawable.type_traditional); + gcIcons.put("virtual", R.drawable.type_virtual); + gcIcons.put("webcam", R.drawable.type_webcam); + gcIcons.put("wherigo", R.drawable.type_wherigo); + gcIcons.put("gchq", R.drawable.type_hq); + gcIcons.put("mystery", R.drawable.type_mystery); + } + + if (cache.name != null && cache.name.length() > 0) { + base.setTitle(activity, cache.name); + } else { + base.setTitle(activity, geocode.toUpperCase()); + } + + inflater = activity.getLayoutInflater(); + geocode = cache.geocode.toUpperCase(); + + ScrollView scroll = (ScrollView) findViewById(R.id.details_list_box); + scroll.setVisibility(View.VISIBLE); + + LinearLayout detailsList = (LinearLayout) findViewById(R.id.details_list); + detailsList.removeAllViews(); + + // actionbar icon + if (cache.type != null && gcIcons.containsKey(cache.type) == true) { // cache icon + ((TextView) findViewById(R.id.actionbar_title)).setCompoundDrawablesWithIntrinsicBounds((Drawable) activity.getResources().getDrawable(gcIcons.get(cache.type)), null, null, null); + } else { // unknown cache type, "mystery" icon + ((TextView) findViewById(R.id.actionbar_title)).setCompoundDrawablesWithIntrinsicBounds((Drawable) activity.getResources().getDrawable(gcIcons.get("mystery")), null, null, null); + } + + // cache name (full name) + itemLayout = (RelativeLayout) inflater.inflate(R.layout.cache_item, null); + itemName = (TextView) itemLayout.findViewById(R.id.name); + itemValue = (TextView) itemLayout.findViewById(R.id.value); + + itemName.setText(res.getString(R.string.cache_name)); + itemValue.setText(Html.fromHtml(cache.name).toString()); + detailsList.addView(itemLayout); + + // cache type + itemLayout = (RelativeLayout) inflater.inflate(R.layout.cache_item, null); + itemName = (TextView) itemLayout.findViewById(R.id.name); + itemValue = (TextView) itemLayout.findViewById(R.id.value); + + itemName.setText(res.getString(R.string.cache_type)); + + String size = null; + if (cache.size != null && cache.size.length() > 0) { + size = " (" + cache.size + ")"; + } else { + size = ""; + } + + if (cgBase.cacheTypesInv.containsKey(cache.type) == true) { // cache icon + itemValue.setText(cgBase.cacheTypesInv.get(cache.type) + size); + } else { + itemValue.setText(cgBase.cacheTypesInv.get("mystery") + size); + } + detailsList.addView(itemLayout); + + // gc-code + itemLayout = (RelativeLayout) inflater.inflate(R.layout.cache_item, null); + itemName = (TextView) itemLayout.findViewById(R.id.name); + itemValue = (TextView) itemLayout.findViewById(R.id.value); + + itemName.setText(res.getString(R.string.cache_geocode)); + itemValue.setText(cache.geocode.toUpperCase()); + detailsList.addView(itemLayout); + + // cache state + if (cache.logOffline == true || cache.archived == true || cache.disabled == true || cache.members == true || cache.found == true) { + itemLayout = (RelativeLayout) inflater.inflate(R.layout.cache_item, null); + itemName = (TextView) itemLayout.findViewById(R.id.name); + itemValue = (TextView) itemLayout.findViewById(R.id.value); + + itemName.setText(res.getString(R.string.cache_status)); + + StringBuilder state = new StringBuilder(); + if (cache.logOffline == true) { + if (state.length() > 0) { + state.append(", "); + } + state.append(res.getString(R.string.cache_status_offline_log)); + } + if (cache.found == true) { + if (state.length() > 0) { + state.append(", "); + } + state.append(res.getString(R.string.cache_status_found)); + } + if (cache.archived == true) { + if (state.length() > 0) { + state.append(", "); + } + state.append(res.getString(R.string.cache_status_archived)); + } + if (cache.disabled == true) { + if (state.length() > 0) { + state.append(", "); + } + state.append(res.getString(R.string.cache_status_disabled)); + } + if (cache.members == true) { + if (state.length() > 0) { + state.append(", "); + } + state.append(res.getString(R.string.cache_status_premium)); + } + + itemValue.setText(state.toString()); + detailsList.addView(itemLayout); + + state = null; + } + + // distance + itemLayout = (RelativeLayout) inflater.inflate(R.layout.cache_item, null); + itemName = (TextView) itemLayout.findViewById(R.id.name); + itemValue = (TextView) itemLayout.findViewById(R.id.value); + + itemName.setText(res.getString(R.string.cache_distance)); + if (cache.distance != null) { + itemValue.setText("~" + base.getHumanDistance(cache.distance)); + } else { + itemValue.setText("--"); + } + detailsList.addView(itemLayout); + cacheDistance = itemValue; + + // difficulty + if (cache.difficulty != null && cache.difficulty > 0) { + addStarRating(detailsList, res.getString(R.string.cache_difficulty), cache.difficulty); + } + + // terrain + if (cache.terrain != null && cache.terrain > 0) { + addStarRating(detailsList, res.getString(R.string.cache_terrain), cache.terrain); + } + + // rating + if (cache.rating != null && cache.rating > 0) { + itemLayout = addStarRating(detailsList, res.getString(R.string.cache_rating), cache.rating); + if (cache.votes != null) { + final TextView itemAddition = (TextView)itemLayout.findViewById(R.id.addition); + itemAddition.setText("(" + cache.votes + ")"); + itemAddition.setVisibility(View.VISIBLE); + } + } + + // favourite count + if (cache.favouriteCnt != null) { + itemLayout = (RelativeLayout) inflater.inflate(R.layout.cache_item, null); + itemName = (TextView) itemLayout.findViewById(R.id.name); + itemValue = (TextView) itemLayout.findViewById(R.id.value); + + itemName.setText(res.getString(R.string.cache_favourite)); + itemValue.setText(String.format("%d", cache.favouriteCnt) + "×"); + detailsList.addView(itemLayout); + } + + // cache author + if ((cache.owner != null && cache.owner.length() > 0) || (cache.ownerReal != null && cache.ownerReal.length() > 0)) { + itemLayout = (RelativeLayout) inflater.inflate(R.layout.cache_item, null); + itemName = (TextView) itemLayout.findViewById(R.id.name); + itemValue = (TextView) itemLayout.findViewById(R.id.value); + + itemName.setText(res.getString(R.string.cache_owner)); + if (cache.owner != null && cache.owner.length() > 0) { + itemValue.setText(Html.fromHtml(cache.owner), TextView.BufferType.SPANNABLE); + } else if (cache.ownerReal != null && cache.ownerReal.length() > 0) { + itemValue.setText(Html.fromHtml(cache.ownerReal), TextView.BufferType.SPANNABLE); + } + itemValue.setOnClickListener(new userActions()); + detailsList.addView(itemLayout); + } + + // cache hidden + if (cache.hidden != null && cache.hidden.getTime() > 0) { + itemLayout = (RelativeLayout) inflater.inflate(R.layout.cache_item, null); + itemName = (TextView) itemLayout.findViewById(R.id.name); + itemValue = (TextView) itemLayout.findViewById(R.id.value); + + if (cache.type != null && (cache.type.equalsIgnoreCase("event") == true || cache.type.equalsIgnoreCase("mega") == true || cache.type.equalsIgnoreCase("cito") == true)) { + itemName.setText(res.getString(R.string.cache_event)); + } else { + itemName.setText(res.getString(R.string.cache_hidden)); + } + itemValue.setText(cgBase.dateOut.format(cache.hidden)); + detailsList.addView(itemLayout); + } + + // cache location + if (cache.location != null && cache.location.length() > 0) { + itemLayout = (RelativeLayout) inflater.inflate(R.layout.cache_item, null); + itemName = (TextView) itemLayout.findViewById(R.id.name); + itemValue = (TextView) itemLayout.findViewById(R.id.value); + + itemName.setText(res.getString(R.string.cache_location)); + itemValue.setText(cache.location); + detailsList.addView(itemLayout); + } + + // cache coordinates + if (cache.latitude != null && cache.longitude != null) { + itemLayout = (RelativeLayout) inflater.inflate(R.layout.cache_item, null); + itemName = (TextView) itemLayout.findViewById(R.id.name); + itemValue = (TextView) itemLayout.findViewById(R.id.value); + + itemName.setText(res.getString(R.string.cache_coordinates)); + itemValue.setText(cache.latitudeString + " | " + cache.longitudeString); + detailsList.addView(itemLayout); + } + + // cache attributes + if (cache.attributes != null && cache.attributes.size() > 0) { + final LinearLayout attribBox = (LinearLayout) findViewById(R.id.attributes_box); + final TextView attribView = (TextView) findViewById(R.id.attributes); + + StringBuilder buffer = new StringBuilder(); + String attribute; + for (int i = 0; i < cache.attributes.size(); i++) { + attribute = cache.attributes.get(i); + + // dynamically search for a translation of the attribute + int id = res.getIdentifier("attribute_" + attribute, "string", base.context.getPackageName()); + if (id > 0) { + String translated = res.getString(id); + if (translated != null && translated.length() > 0) { + attribute = translated; + } + } + if (buffer.length() > 0) { + buffer.append('\n'); + } + buffer.append(attribute); + } + + attribView.setText(buffer); + attribBox.setVisibility(View.VISIBLE); + } + + // cache inventory + if (cache.inventory != null && cache.inventory.size() > 0) { + final LinearLayout inventBox = (LinearLayout) findViewById(R.id.inventory_box); + final TextView inventView = (TextView) findViewById(R.id.inventory); + + StringBuilder inventoryString = new StringBuilder(); + for (cgTrackable inventoryItem : cache.inventory) { + if (inventoryString.length() > 0) { + inventoryString.append("\n"); + } + // avoid HTML parsing where possible + if (inventoryItem.name.indexOf('<') >= 0 || inventoryItem.name.indexOf('&') >= 0 ) { + inventoryString.append(Html.fromHtml(inventoryItem.name).toString()); + } + else { + inventoryString.append(inventoryItem.name); + } + } + inventView.setText(inventoryString); + inventBox.setClickable(true); + inventBox.setOnClickListener(new selectTrackable()); + inventBox.setVisibility(View.VISIBLE); + } + + // offline use + final TextView offlineText = (TextView) findViewById(R.id.offline_text); + final Button offlineRefresh = (Button) findViewById(R.id.offline_refresh); + final Button offlineStore = (Button) findViewById(R.id.offline_store); + + if (cache.reason >= 1) { + Long diff = (System.currentTimeMillis() / (60 * 1000)) - (cache.detailedUpdate / (60 * 1000)); // minutes + + String ago = ""; + if (diff < 15) { + ago = res.getString(R.string.cache_offline_time_mins_few); + } else if (diff < 50) { + ago = res.getString(R.string.cache_offline_time_about) + " " + diff + " " + res.getString(R.string.cache_offline_time_mins); + } else if (diff < 90) { + ago = res.getString(R.string.cache_offline_time_about) + " " + res.getString(R.string.cache_offline_time_hour); + } else if (diff < (48 * 60)) { + ago = res.getString(R.string.cache_offline_time_about) + " " + (diff / 60) + " " + res.getString(R.string.cache_offline_time_hours); + } else { + ago = res.getString(R.string.cache_offline_time_about) + " " + (diff / (24 * 60)) + " " + res.getString(R.string.cache_offline_time_days); + } + + offlineText.setText(res.getString(R.string.cache_offline_stored) + "\n" + ago); + + offlineRefresh.setVisibility(View.VISIBLE); + offlineRefresh.setClickable(true); + offlineRefresh.setOnClickListener(new storeCache()); + + offlineStore.setText(res.getString(R.string.cache_offline_drop)); + offlineStore.setClickable(true); + offlineStore.setOnClickListener(new dropCache()); + } else { + offlineText.setText(res.getString(R.string.cache_offline_not_ready)); + + offlineRefresh.setVisibility(View.VISIBLE); + offlineRefresh.setClickable(true); + offlineRefresh.setOnClickListener(new refreshCache()); + + offlineStore.setText(res.getString(R.string.cache_offline_store)); + offlineStore.setClickable(true); + offlineStore.setOnClickListener(new storeCache()); + } + + // cache short desc + if (cache.shortdesc != null && cache.shortdesc.length() > 0) { + ((LinearLayout) findViewById(R.id.desc_box)).setVisibility(View.VISIBLE); + + TextView descView = (TextView) findViewById(R.id.shortdesc); + descView.setVisibility(View.VISIBLE); + descView.setText(Html.fromHtml(cache.shortdesc.trim(), new cgHtmlImg(activity, settings, geocode, true, cache.reason, false), null), TextView.BufferType.SPANNABLE); + descView.setMovementMethod(LinkMovementMethod.getInstance()); + } + + // cache long desc + if (longDescDisplayed == true) { + if (longDesc == null && cache != null && cache.description != null) { + longDesc = Html.fromHtml(cache.description.trim(), new cgHtmlImg(activity, settings, geocode, true, cache.reason, false), null); + } + + if (longDesc != null && longDesc.length() > 0) { + ((LinearLayout) findViewById(R.id.desc_box)).setVisibility(View.VISIBLE); + + TextView descView = (TextView) findViewById(R.id.description); + descView.setVisibility(View.VISIBLE); + descView.setText(longDesc, TextView.BufferType.SPANNABLE); + descView.setMovementMethod(LinkMovementMethod.getInstance()); + + Button showDesc = (Button) findViewById(R.id.show_description); + showDesc.setVisibility(View.GONE); + showDesc.setOnTouchListener(null); + showDesc.setOnClickListener(null); + } + } else if (longDescDisplayed == false && cache.description != null && cache.description.length() > 0) { + ((LinearLayout) findViewById(R.id.desc_box)).setVisibility(View.VISIBLE); + + Button showDesc = (Button) findViewById(R.id.show_description); + showDesc.setVisibility(View.VISIBLE); + showDesc.setOnClickListener(new View.OnClickListener() { + public void onClick(View arg0) { + loadLongDesc(); + } + }); + } + + // waypoints + LinearLayout waypoints = (LinearLayout) findViewById(R.id.waypoints); + waypoints.removeAllViews(); + + if (cache.waypoints != null && cache.waypoints.size() > 0) { + LinearLayout waypointView; + + // sort waypoints: PP, Sx, FI, OWN + ArrayList<cgWaypoint> sortedWaypoints = new ArrayList<cgWaypoint>(cache.waypoints); + Collections.sort(sortedWaypoints, new Comparator<cgWaypoint>() { + + @Override + public int compare(cgWaypoint wayPoint1, cgWaypoint wayPoint2) { + + return order(wayPoint1) - order(wayPoint2); + } + + private int order(cgWaypoint waypoint) { + if (waypoint.prefix == null || waypoint.prefix.length() == 0) { + return 0; + } + // check only the first character. sometimes there are inconsistencies like FI or FN for the FINAL + char firstLetter = Character.toUpperCase(waypoint.prefix.charAt(0)); + switch (firstLetter) { + case 'P' : return -100; // parking + case 'S' : { // stage N + try { + Integer stageNumber = Integer.valueOf(waypoint.prefix.substring(1)); + return stageNumber; + } catch (NumberFormatException e) { + // nothing + } + return 0; + } + case 'F' : return 1000; // final + case 'O' : return 10000; // own + } + return 0; + }}); + + for (cgWaypoint wpt : sortedWaypoints) { + waypointView = (LinearLayout) inflater.inflate(R.layout.waypoint_item, null); + final TextView identification = (TextView) waypointView.findViewById(R.id.identification); + + ((TextView) waypointView.findViewById(R.id.type)).setText(cgBase.waypointTypes.get(wpt.type)); + if (wpt.prefix.equalsIgnoreCase("OWN") == false) { + identification.setText(wpt.prefix.trim() + "/" + wpt.lookup.trim()); + } else { + identification.setText(res.getString(R.string.waypoint_custom)); + } + + if (wpt.name.trim().length() == 0) { + ((TextView) waypointView.findViewById(R.id.name)).setText(base.formatCoordinate(wpt.latitude, "lat", true) + " | " + base.formatCoordinate(wpt.longitude, "lon", true)); + } else { + // avoid HTML parsing + if (wpt.name.indexOf('<') >= 0 || wpt.name.indexOf('&') >= 0) { + ((TextView) waypointView.findViewById(R.id.name)).setText(Html.fromHtml(wpt.name.trim()), TextView.BufferType.SPANNABLE); + } + else { + ((TextView) waypointView.findViewById(R.id.name)).setText(wpt.name.trim()); + } + } + // avoid HTML parsing + if (wpt.note.indexOf('<') >= 0 || wpt.note.indexOf('&') >= 0) { + ((TextView) waypointView.findViewById(R.id.note)).setText(Html.fromHtml(wpt.note.trim()), TextView.BufferType.SPANNABLE); + } + else { + ((TextView) waypointView.findViewById(R.id.note)).setText(wpt.note.trim()); + } + + waypointView.setOnClickListener(new waypointInfo(wpt.id)); + + waypoints.addView(waypointView); + } + } + + Button addWaypoint = (Button) findViewById(R.id.add_waypoint); + addWaypoint.setClickable(true); + addWaypoint.setOnClickListener(new addWaypoint()); + + // cache hint + if (cache.hint != null && cache.hint.length() > 0) { + ((LinearLayout) findViewById(R.id.hint_box)).setVisibility(View.VISIBLE); + TextView hintView = ((TextView) findViewById(R.id.hint)); + hintView.setText(cgBase.rot13(cache.hint.trim())); + hintView.setClickable(true); + hintView.setOnClickListener(new codeHint()); + } else { + ((LinearLayout) findViewById(R.id.hint_box)).setVisibility(View.GONE); + TextView hintView = ((TextView) findViewById(R.id.hint)); + hintView.setClickable(false); + hintView.setOnClickListener(null); + } + + if (geo != null && geo.latitudeNow != null && geo.longitudeNow != null && cache != null && cache.latitude != null && cache.longitude != null) { + cacheDistance.setText(base.getHumanDistance(cgBase.getDistance(geo.latitudeNow, geo.longitudeNow, cache.latitude, cache.longitude))); + cacheDistance.bringToFront(); + } + } catch (Exception e) { + Log.e(cgSettings.tag, "cgeodetail.setView: " + e.toString()); + } + + if (waitDialog != null && waitDialog.isShowing()) waitDialog.dismiss(); + if (storeDialog != null && storeDialog.isShowing()) storeDialog.dismiss(); + if (dropDialog != null && dropDialog.isShowing()) dropDialog.dismiss(); + if (refreshDialog != null && refreshDialog.isShowing()) refreshDialog.dismiss(); + + displayLogs(); + + if (geo != null) geoUpdate.updateLoc(geo); + } + + private RelativeLayout addStarRating(final LinearLayout detailsList, final String name, final float value) { + RelativeLayout itemLayout = (RelativeLayout) inflater.inflate(R.layout.cache_layout, null); + TextView itemName = (TextView) itemLayout.findViewById(R.id.name); + TextView itemValue = (TextView) itemLayout.findViewById(R.id.value); + LinearLayout itemStars = (LinearLayout) itemLayout.findViewById(R.id.stars); + + itemName.setText(name); + itemValue.setText(String.format(Locale.getDefault(), "%.1f", value) + ' ' + res.getString(R.string.cache_rating_of) + " 5"); + for (int i = 0; i <= 4; i++) { + ImageView star = (ImageView) inflater.inflate(R.layout.star, null); + if ((value - i) >= 1.0) { + star.setImageResource(R.drawable.star_on); + } else if ((value - i) > 0.0) { + star.setImageResource(R.drawable.star_half); + } else { + star.setImageResource(R.drawable.star_off); + } + itemStars.addView(star, (1 + i)); + } + detailsList.addView(itemLayout); + return itemLayout; + } + + private void displayLogs() { + // cache logs + TextView textView = (TextView) findViewById(R.id.logcount); + int logCounter = 0; + if (cache != null && cache.logCounts != null) { + final StringBuffer buff = new StringBuffer(); + buff.append(res.getString(R.string.cache_log_types)); + buff.append(": "); + + // sort the log counts by type id ascending. that way the FOUND, DNF log types are the first and most visible ones + ArrayList<Entry<Integer, Integer>> sortedLogCounts = new ArrayList<Entry<Integer,Integer>>(); + sortedLogCounts.addAll(cache.logCounts.entrySet()); + Collections.sort(sortedLogCounts, new Comparator<Entry<Integer, Integer>>() { + + @Override + public int compare(Entry<Integer, Integer> logCountItem1, + Entry<Integer, Integer> logCountItem2) { + return logCountItem1.getKey().compareTo(logCountItem2.getKey()); + }}); + for (Entry<Integer, Integer> pair : sortedLogCounts) { + int logTypeId = pair.getKey().intValue(); + String logTypeLabel = cgBase.logTypes1.get(logTypeId); + // it may happen that the label is unknown -> then avoid any output for this type + if (logTypeLabel != null) { + if (logCounter > 0) { + buff.append(", "); + } + buff.append(pair.getValue().intValue()); + buff.append("× "); + buff.append(logTypeLabel); + } + logCounter ++; + } + textView.setText(buff.toString()); + } + // it may happen, that the logCounts map is available, but every log type has zero counts, + // therefore check again for the number of counted logs + if (logCounter > 0) { + textView.setVisibility(View.VISIBLE); + } else { + textView.setVisibility(View.GONE); + } + + // cache logs + LinearLayout listView = (LinearLayout) findViewById(R.id.log_list); + listView.removeAllViews(); + + RelativeLayout rowView; + + if (cache != null && cache.logs != null) { + for (cgLog log : cache.logs) { + rowView = (RelativeLayout) inflater.inflate(R.layout.log_item, null); + + if (log.date > 0) { + final Date logDate = new Date(log.date); + ((TextView) rowView.findViewById(R.id.added)).setText(cgBase.dateOutShort.format(logDate)); + } + + if (cgBase.logTypes1.containsKey(log.type) == true) { + ((TextView) rowView.findViewById(R.id.type)).setText(cgBase.logTypes1.get(log.type)); + } else { + ((TextView) rowView.findViewById(R.id.type)).setText(cgBase.logTypes1.get(4)); // note if type is unknown + } + // avoid parsing HTML if not necessary + if (log.author.indexOf('<') >= 0 || log.author.indexOf('&') >= 0) { + ((TextView) rowView.findViewById(R.id.author)).setText(Html.fromHtml(log.author), TextView.BufferType.SPANNABLE); + } + else { + ((TextView) rowView.findViewById(R.id.author)).setText(log.author); + } + + if (log.found == -1) { + ((TextView) rowView.findViewById(R.id.count)).setVisibility(View.GONE); + } else if (log.found == 0) { + ((TextView) rowView.findViewById(R.id.count)).setText(res.getString(R.string.cache_count_no)); + } else if (log.found == 1) { + ((TextView) rowView.findViewById(R.id.count)).setText(res.getString(R.string.cache_count_one)); + } else { + ((TextView) rowView.findViewById(R.id.count)).setText(log.found + " " + res.getString(R.string.cache_count_more)); + } + // avoid parsing HTML if not necessary + if (log.log.indexOf('<') >= 0 || log.log.indexOf('&') >= 0) { + ((TextView) rowView.findViewById(R.id.log)).setText(Html.fromHtml(log.log, new cgHtmlImg(activity, settings, null, false, cache.reason, false), null), TextView.BufferType.SPANNABLE); + } + else { + ((TextView) rowView.findViewById(R.id.log)).setText(log.log); + } + + final ImageView markFound = (ImageView) rowView.findViewById(R.id.found_mark); + final ImageView markDNF = (ImageView) rowView.findViewById(R.id.dnf_mark); + final ImageView markDisabled = (ImageView) rowView.findViewById(R.id.disabled_mark); + if (log.type == 2 || log.type == 9 || log.type == 10) { // found, will attend, attended + markFound.setVisibility(View.VISIBLE); + markDNF.setVisibility(View.GONE); + markDisabled.setVisibility(View.GONE); + } else if (log.type == 3) { // did not find + markFound.setVisibility(View.GONE); + markDNF.setVisibility(View.VISIBLE); + markDisabled.setVisibility(View.GONE); + } else if (log.type == 7 || log.type == 8) { // disabled, archived + markFound.setVisibility(View.GONE); + markDNF.setVisibility(View.GONE); + markDisabled.setVisibility(View.VISIBLE); + } else { + markFound.setVisibility(View.GONE); + markDNF.setVisibility(View.GONE); + markDisabled.setVisibility(View.GONE); + } + + ((TextView) rowView.findViewById(R.id.author)).setOnClickListener(new userActions()); + ((TextView) rowView.findViewById(R.id.log)).setOnClickListener(new decryptLog()); + + listView.addView(rowView); + } + + if (cache.logs.size() > 0) { + ((LinearLayout) findViewById(R.id.log_box)).setVisibility(View.VISIBLE); + } + } + } + + private class loadCache extends Thread { + + private Handler handler = null; + private String geocode = null; + private String guid = null; + + public loadCache(Handler handlerIn, String geocodeIn, String guidIn) { + handler = handlerIn; + geocode = geocodeIn; + guid = guidIn; + + if (geocode == null && guid == null) { + warning.showToast(res.getString(R.string.err_detail_cache_forgot)); + + finish(); + return; + } + } + + @Override + public void run() { + HashMap<String, String> params = new HashMap<String, String>(); + if (geocode != null && geocode.length() > 0) { + params.put("geocode", geocode); + } else if (guid != null && guid.length() > 0) { + params.put("guid", guid); + } else { + return; + } + + searchId = base.searchByGeocode(params, 0, false); + + handler.sendMessage(new Message()); + } + } + + private class loadMapPreview extends Thread { + private cgCache cache = null; + private Handler handler = null; + + public loadMapPreview(cgCache cacheIn, Handler handlerIn) { + cache = cacheIn; + handler = handlerIn; + } + + @Override + public void run() { + if (cache == null || cache.latitude == null || cache.longitude == null) { + return; + } + + BitmapDrawable image = null; + + try { + final String latlonMap = String.format((Locale) null, "%.6f", cache.latitude) + "," + String.format((Locale) null, "%.6f", cache.longitude); + final Display display = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); + + int width = display.getWidth(); + int height = (int) (90 * pixelRatio); + + String markerUrl = cgBase.urlencode_rfc3986("http://cgeo.carnero.cc/_markers/my_location_mdpi.png"); + + cgHtmlImg mapGetter = new cgHtmlImg(activity, settings, cache.geocode, false, 0, false); + image = mapGetter.getDrawable("http://maps.google.com/maps/api/staticmap?center=" + latlonMap + "&zoom=15&size=" + width + "x" + height + "&maptype=terrain&markers=icon%3A" + markerUrl + "%7C" + latlonMap + "&sensor=false"); + Message message = handler.obtainMessage(0, image); + handler.sendMessage(message); + } catch (Exception e) { + Log.w(cgSettings.tag, "cgeodetail.loadMapPreview.run: " + e.toString()); + } + } + } + + public void loadLongDesc() { + if (activity != null && (waitDialog == null || waitDialog.isShowing() == false)) { + descDialog = ProgressDialog.show(activity, null, res.getString(R.string.cache_dialog_loading_description), true); + descDialog.setCancelable(true); + } + + threadLongDesc = new loadLongDesc(loadDescriptionHandler); + threadLongDesc.start(); + } + + private class loadLongDesc extends Thread { + private Handler handler = null; + + public loadLongDesc(Handler handlerIn) { + handler = handlerIn; + } + + @Override + public void run() { + if (cache == null || cache.description == null || handler == null) { + return; + } + + longDesc = Html.fromHtml(cache.description.trim(), new cgHtmlImg(activity, settings, geocode, true, cache.reason, false), null); + handler.sendMessage(new Message()); + } + } + + public ArrayList<cgCoord> getCoordinates() { + cgCoord coords = null; + ArrayList<cgCoord> coordinates = new ArrayList<cgCoord>(); + + try { + // cache + coords = new cgCoord(); + coords.type = "cache"; + if (name != null && name.length() > 0) { + coords.name = name; + } else { + coords.name = geocode.toUpperCase(); + } + coords.latitude = cache.latitude; + coords.longitude = cache.longitude; + coordinates.add(coords); + } catch (Exception e) { + Log.e(cgSettings.tag, "cgeodetail.getCoordinates (cache): " + e.toString()); + } + + try { + // waypoints + for (cgWaypoint waypoint : cache.waypoints) { + if (waypoint.latitude == null || waypoint.longitude == null) { + continue; + } + + coords = new cgCoord(); + coords.type = "waypoint"; + coords.name = waypoint.name; + coords.latitude = waypoint.latitude; + coords.longitude = waypoint.longitude; + coordinates.add(coords); + } + } catch (Exception e) { + Log.e(cgSettings.tag, "cgeodetail.getCoordinates (waypoint): " + e.toString()); + } + + return coordinates; + } + + private void showOnMap() { + Intent mapIntent = new Intent(activity, settings.getMapFactory().getMapClass()); + mapIntent.putExtra("detail", true); + mapIntent.putExtra("searchid", searchId); + + activity.startActivity(mapIntent); + } + + private void cachesAround() { + cgeocaches cachesActivity = new cgeocaches(); + + Intent cachesIntent = new Intent(activity, cachesActivity.getClass()); + cachesIntent.putExtra("type", "coordinate"); + cachesIntent.putExtra("latitude", cache.latitude); + cachesIntent.putExtra("longitude", cache.longitude); + cachesIntent.putExtra("cachetype", settings.cacheType); + + activity.startActivity(cachesIntent); + + finish(); + } + + private void addToCalendar() { + String[] projection = new String[] { "_id", "displayName" }; + Uri calendarProvider = null; + final int sdk = new Integer(Build.VERSION.SDK).intValue(); + if (sdk >= 8) { + calendarProvider = Uri.parse("content://com.android.calendar/calendars"); + } else { + calendarProvider = Uri.parse("content://calendar/calendars"); + } + + Cursor cursor = managedQuery(calendarProvider, projection, "selected=1", null, null); + + calendars.clear(); + int cnt = 0; + if (cursor != null) { + cnt = cursor.getCount(); + + if (cnt > 0) { + cursor.moveToFirst(); + + int calId = 0; + String calIdPre = null; + String calName = null; + int calIdIn = cursor.getColumnIndex("_id"); + int calNameIn = cursor.getColumnIndex("displayName"); + + do { + calIdPre = cursor.getString(calIdIn); + if (calIdPre != null) { + calId = new Integer(calIdPre); + } + calName = cursor.getString(calNameIn); + + if (calId > 0 && calName != null) { + calendars.put(calId, calName); + } + } while (cursor.moveToNext() == true); + } + } + + final CharSequence[] items = calendars.values().toArray(new CharSequence[calendars.size()]); + + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setTitle(R.string.cache_calendars); + builder.setItems(items, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + addToCalendarFn(item); + } + }); + AlertDialog alert = builder.create(); + alert.show(); + } + + private void addToCalendarFn(int index) { + if (calendars == null || calendars.isEmpty() == true) { + return; + } + + try { + Uri calendarProvider = null; + final int sdk = new Integer(Build.VERSION.SDK).intValue(); + if (sdk >= 8) { + calendarProvider = Uri.parse("content://com.android.calendar/events"); + } else { + calendarProvider = Uri.parse("content://calendar/events"); + } + + final Integer[] keys = calendars.keySet().toArray(new Integer[calendars.size()]); + final Integer calId = keys[index]; + + final Date eventDate = cache.hidden; + eventDate.setHours(0); + eventDate.setMinutes(0); + eventDate.setSeconds(0); + + StringBuilder description = new StringBuilder(); + description.append("http://coord.info/"); + description.append(cache.geocode.toUpperCase()); + description.append("\n\n"); + if (cache.shortdesc != null && cache.shortdesc.length() > 0) { + description.append(Html.fromHtml(cache.shortdesc).toString()); + } + + ContentValues event = new ContentValues(); + event.put("calendar_id", calId); + event.put("dtstart", eventDate.getTime() + 43200000); // noon + event.put("dtend", eventDate.getTime() + 43200000 + 3600000); // + one hour + event.put("eventTimezone", "UTC"); + event.put("title", Html.fromHtml(cache.name).toString()); + event.put("description", description.toString()); + String location = ""; + if (cache.latitudeString != null && cache.latitudeString.length() > 0 && cache.longitudeString != null && cache.longitudeString.length() > 0) { + location += cache.latitudeString + " " + cache.longitudeString; + } + if (cache.location != null && cache.location.length() > 0) { + boolean addParenteses = false; + if (location.length() > 0) { + addParenteses = true; + location += " ("; + } + + location += Html.fromHtml(cache.location).toString(); + if (addParenteses) { + location += ")"; + } + } + if (location.length() > 0) { + event.put("eventLocation", location); + } + event.put("allDay", 1); + event.put("hasAlarm", 0); + + getContentResolver().insert(calendarProvider, event); + + warning.showToast(res.getString(R.string.event_success)); + } catch (Exception e) { + warning.showToast(res.getString(R.string.event_fail)); + + Log.e(cgSettings.tag, "cgeodetail.addToCalendarFn: " + e.toString()); + } + } + + private void navigateTo() { + if (cache == null || cache.latitude == null || cache.longitude == null) { + warning.showToast(res.getString(R.string.err_location_unknown)); + } + + cgeonavigate navigateActivity = new cgeonavigate(); + + Intent navigateIntent = new Intent(activity, navigateActivity.getClass()); + navigateIntent.putExtra("latitude", cache.latitude); + navigateIntent.putExtra("longitude", cache.longitude); + navigateIntent.putExtra("geocode", cache.geocode.toUpperCase()); + navigateIntent.putExtra("name", cache.name); + + if (cgeonavigate.coordinates != null) { + cgeonavigate.coordinates.clear(); + } + cgeonavigate.coordinates = getCoordinates(); + activity.startActivity(navigateIntent); + } + + private void radarTo() { + try { + if (cgBase.isIntentAvailable(activity, "com.google.android.radar.SHOW_RADAR") == true) { + Intent radarIntent = new Intent("com.google.android.radar.SHOW_RADAR"); + radarIntent.putExtra("latitude", new Float(cache.latitude)); + radarIntent.putExtra("longitude", new Float(cache.longitude)); + activity.startActivity(radarIntent); + } else { + AlertDialog.Builder dialog = new AlertDialog.Builder(activity); + dialog.setTitle(res.getString(R.string.err_radar_title)); + dialog.setMessage(res.getString(R.string.err_radar_message)); + dialog.setCancelable(true); + dialog.setPositiveButton("yes", new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface dialog, int id) { + try { + activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=pname:com.eclipsim.gpsstatus2"))); + dialog.cancel(); + } catch (Exception e) { + warning.showToast(res.getString(R.string.err_radar_market)); + Log.e(cgSettings.tag, "cgeodetail.radarTo.onClick: " + e.toString()); + } + } + }); + dialog.setNegativeButton("no", new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + + AlertDialog alert = dialog.create(); + alert.show(); + } + } catch (Exception e) { + warning.showToast(res.getString(R.string.err_radar_generic)); + Log.e(cgSettings.tag, "cgeodetail.radarTo: " + e.toString()); + } + } + + public void shareCache() { + if (geocode == null && cache == null) { + return; + } + + final Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("text/plain"); + + if (cache != null && cache.geocode != null) { + String subject = cache.geocode.toUpperCase(); + if (cache.name != null && cache.name.length() > 0){ + subject = subject + " - " + cache.name; + } + intent.putExtra(Intent.EXTRA_SUBJECT, "Geocache " + subject); + intent.putExtra(Intent.EXTRA_TEXT, "http://coord.info/" + cache.geocode.toUpperCase()); + } else if (geocode != null) { + intent.putExtra(Intent.EXTRA_SUBJECT, "Geocache " + geocode.toUpperCase()); + intent.putExtra(Intent.EXTRA_TEXT, "http://coord.info/" + geocode.toUpperCase()); + } + + startActivity(Intent.createChooser(intent, res.getText(R.string.action_bar_share_title))); + } + + private class waypointInfo implements View.OnClickListener { + private int id = -1; + + public waypointInfo(int idIn) { + id = idIn; + } + + public void onClick(View arg0) { + Intent waypointIntent = new Intent(activity, cgeowaypoint.class); + waypointIntent.putExtra("waypoint", id); + waypointIntent.putExtra("geocode", cache.geocode); + activity.startActivity(waypointIntent); + } + } + + private void logVisit() { + Intent logVisitIntent = new Intent(activity, cgeovisit.class); + logVisitIntent.putExtra("id", cache.cacheid); + logVisitIntent.putExtra("geocode", cache.geocode.toUpperCase()); + logVisitIntent.putExtra("type", cache.type.toLowerCase()); + logVisitIntent.putExtra("found", cache.found); + activity.startActivity(logVisitIntent); + } + + private void showSpoilers() { + if (cache == null || cache.spoilers == null || cache.spoilers.isEmpty() == true) { + warning.showToast(res.getString(R.string.err_detail_no_spoiler)); + } + + Intent spoilersIntent = new Intent(activity, cgeospoilers.class); + spoilersIntent.putExtra("geocode", geocode.toUpperCase()); + activity.startActivity(spoilersIntent); + } + + private void showSmaps() { + if (cache == null || cache.reason == 0) { + warning.showToast(res.getString(R.string.err_detail_no_map_static)); + } + + Intent smapsIntent = new Intent(activity, cgeosmaps.class); + smapsIntent.putExtra("geocode", geocode.toUpperCase()); + activity.startActivity(smapsIntent); + } + + public class codeHint implements View.OnClickListener { + public void onClick(View arg0) { + // code hint + TextView hintView = ((TextView) findViewById(R.id.hint)); + hintView.setText(cgBase.rot13(hintView.getText().toString())); + + } + } + + private class update extends cgUpdateLoc { + @Override + public void updateLoc(cgGeo geo) { + if (geo == null) { + return; + } + + try { + StringBuilder dist = new StringBuilder(); + + if (geo.latitudeNow != null && geo.longitudeNow != null && cache != null && cache.latitude != null && cache.longitude != null) { + dist.append(base.getHumanDistance(cgBase.getDistance(geo.latitudeNow, geo.longitudeNow, cache.latitude, cache.longitude))); + } + + if (cache.elevation != null) { + Double diff = null; + if (geo.altitudeNow != null) { + diff = (cache.elevation - geo.altitudeNow); + } + + if (diff != null && diff >= 0) { + dist.append(" ↗"); + if (settings.units == cgSettings.unitsImperial) { + dist.append(String.format(Locale.getDefault(), "%.0f", (Math.abs(diff) * 3.2808399))); + dist.append(" ft"); + } else { + dist.append(String.format(Locale.getDefault(), "%.0f", (Math.abs(diff)))); + dist.append(" m"); + } + } else if (diff != null && diff < 0) { + dist.append(" ↘"); + if (settings.units == cgSettings.unitsImperial) { + dist.append(String.format(Locale.getDefault(), "%.0f", (Math.abs(diff) * 3.2808399))); + dist.append(" ft"); + } else { + dist.append(String.format(Locale.getDefault(), "%.0f", (Math.abs(diff)))); + dist.append(" m"); + } + } + } + + cacheDistance.setText(dist.toString()); + cacheDistance.bringToFront(); + } catch (Exception e) { + Log.w(cgSettings.tag, "Failed to update location."); + } + } + } + + private class selectTrackable implements View.OnClickListener { + public void onClick(View arg0) { + // show list of trackables + try { + Intent trackablesIntent = new Intent(activity, cgeotrackables.class); + trackablesIntent.putExtra("geocode", geocode.toUpperCase()); + activity.startActivity(trackablesIntent); + } catch (Exception e) { + Log.e(cgSettings.tag, "cgeodetail.selectTrackable: " + e.toString()); + } + } + } + + private class storeCache implements View.OnClickListener { + public void onClick(View arg0) { + if (dropDialog != null && dropDialog.isShowing() == true) { + warning.showToast(res.getString(R.string.err_detail_still_removing)); + return; + } + if (refreshDialog != null && refreshDialog.isShowing() == true) { + warning.showToast(res.getString(R.string.err_detail_still_refreshing)); + return; + } + + storeDialog = ProgressDialog.show(activity, res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true); + storeDialog.setCancelable(true); + + if (storeThread != null) { + storeThread.interrupt(); + } + + storeThread = new storeCacheThread(storeCacheHandler); + storeThread.start(); + } + } + + private class refreshCache implements View.OnClickListener { + public void onClick(View arg0) { + if (dropDialog != null && dropDialog.isShowing() == true) { + warning.showToast(res.getString(R.string.err_detail_still_removing)); + return; + } + if (storeDialog != null && storeDialog.isShowing() == true) { + warning.showToast(res.getString(R.string.err_detail_still_saving)); + return; + } + + refreshDialog = ProgressDialog.show(activity, res.getString(R.string.cache_dialog_refresh_title), res.getString(R.string.cache_dialog_refresh_message), true); + refreshDialog.setCancelable(true); + + if (refreshThread != null) { + refreshThread.interrupt(); + } + + refreshThread = new refreshCacheThread(refreshCacheHandler); + refreshThread.start(); + } + } + + private class storeCacheThread extends Thread { + private Handler handler = null; + + public storeCacheThread(Handler handlerIn) { + handler = handlerIn; + } + + @Override + public void run() { + int reason = 1; + if (cache.reason > 1) { + reason = cache.reason; + } + base.storeCache(app, activity, cache, null, reason, handler); + } + } + + private class refreshCacheThread extends Thread { + private Handler handler = null; + + public refreshCacheThread(Handler handlerIn) { + handler = handlerIn; + } + + @Override + public void run() { + app.removeCacheFromCache(geocode); + + final HashMap<String, String> params = new HashMap<String, String>(); + params.put("geocode", cache.geocode); + searchId = base.searchByGeocode(params, 0, true); + + handler.sendEmptyMessage(0); + } + } + + private class dropCache implements View.OnClickListener { + public void onClick(View arg0) { + if (storeDialog != null && storeDialog.isShowing() == true) { + warning.showToast(res.getString(R.string.err_detail_still_saving)); + return; + } + if (refreshDialog != null && refreshDialog.isShowing() == true) { + warning.showToast(res.getString(R.string.err_detail_still_refreshing)); + return; + } + + dropDialog = ProgressDialog.show(activity, res.getString(R.string.cache_dialog_offline_drop_title), res.getString(R.string.cache_dialog_offline_drop_message), true); + dropDialog.setCancelable(false); + Thread thread = new dropCacheThread(dropCacheHandler); + thread.start(); + } + } + + private class dropCacheThread extends Thread { + + private Handler handler = null; + + public dropCacheThread(Handler handlerIn) { + handler = handlerIn; + } + + @Override + public void run() { + base.dropCache(app, activity, cache, handler); + } + } + + private class addWaypoint implements View.OnClickListener { + + public void onClick(View view) { + Intent addWptIntent = new Intent(activity, cgeowaypointadd.class); + + addWptIntent.putExtra("geocode", geocode); + int wpCount = 0; + if (cache.waypoints != null) { + wpCount = cache.waypoints.size(); + } + addWptIntent.putExtra("count", wpCount); + + activity.startActivity(addWptIntent); + } + } + + private class decryptLog implements View.OnClickListener { + + public void onClick(View view) { + if (view == null) { + return; + } + + try { + final TextView logView = (TextView)view; + Spannable span = (Spannable) logView.getText(); + + // I needed to re-implement the base.rot13() encryption here because we must work on + // a SpannableStringBuilder instead of the pure text and we must replace each character inline. + // Otherwise we loose all the images, colors and so on... + SpannableStringBuilder buffer = new SpannableStringBuilder(span); + boolean plaintext = false; + + int length = span.length(); + for (int index = 0; index < length; index++) { + int c = span.charAt(index); + if (c == '[') { + plaintext = true; + } else if (c == ']') { + plaintext = false; + } else if (!plaintext) { + int capitalized = c & 32; + c &= ~capitalized; + c = ((c >= 'A') && (c <= 'Z') ? ((c - 'A' + 13) % 26 + 'A') : c) + | capitalized; + } + buffer.replace(index, index + 1, String.valueOf((char) c)); + } + logView.setText(buffer); + } catch (Exception e) { + // nothing + } + } + } + + private class userActions implements View.OnClickListener { + + public void onClick(View view) { + if (view == null) { + return; + } + + try { + registerForContextMenu(view); + openContextMenu(view); + } catch (Exception e) { + // nothing + } + } + } + + + public void goHome(View view) { + base.goHome(activity); + } + + public void goCompass(View view) { + if (cache == null || cache.latitude == null || cache.longitude == null) { + warning.showToast(res.getString(R.string.cache_coordinates_no)); + + return; + } + + Intent navigateIntent = new Intent(activity, cgeonavigate.class); + navigateIntent.putExtra("latitude", cache.latitude); + navigateIntent.putExtra("longitude", cache.longitude); + navigateIntent.putExtra("geocode", cache.geocode.toUpperCase()); + navigateIntent.putExtra("name", cache.name); + + if (cgeonavigate.coordinates != null) { + cgeonavigate.coordinates.clear(); + } + cgeonavigate.coordinates = getCoordinates(); + activity.startActivity(navigateIntent); + } + + public void goManual(View view) { + try { + AppManualReaderClient.openManual( + "c-geo", + "c:geo-cache-details", + activity, + "http://cgeo.carnero.cc/manual/" + ); + } catch (Exception e) { + // nothing + } + } +} |
