From e61a40fc8a4a3d5ab5a59346eddd1c43bcc4857e Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sat, 14 Jan 2012 15:02:15 +0100 Subject: refactoring: move more widget related classes into own package --- main/src/cgeo/geocaching/CacheListAdapter.java | 832 -------------------- main/src/cgeo/geocaching/cgBase.java | 3 +- main/src/cgeo/geocaching/cgCacheView.java | 23 - main/src/cgeo/geocaching/cgCompass.java | 288 ------- main/src/cgeo/geocaching/cgCompassMini.java | 172 ----- main/src/cgeo/geocaching/cgDirectionImg.java | 28 - main/src/cgeo/geocaching/cgDistanceView.java | 42 - main/src/cgeo/geocaching/cgGPXListAdapter.java | 76 -- main/src/cgeo/geocaching/cgGPXView.java | 9 - main/src/cgeo/geocaching/cgMapfileListAdapter.java | 89 --- main/src/cgeo/geocaching/cgSelectMapfile.java | 7 +- main/src/cgeo/geocaching/cgeocaches.java | 1 + main/src/cgeo/geocaching/cgeogpxes.java | 7 +- main/src/cgeo/geocaching/cgeonavigate.java | 5 +- main/src/cgeo/geocaching/ui/CacheListAdapter.java | 842 +++++++++++++++++++++ main/src/cgeo/geocaching/ui/CacheView.java | 24 + main/src/cgeo/geocaching/ui/CompassMiniView.java | 175 +++++ main/src/cgeo/geocaching/ui/CompassView.java | 291 +++++++ main/src/cgeo/geocaching/ui/DirectionImage.java | 30 + main/src/cgeo/geocaching/ui/DistanceView.java | 43 ++ main/src/cgeo/geocaching/ui/GPXListAdapter.java | 81 ++ main/src/cgeo/geocaching/ui/GPXView.java | 9 + .../src/cgeo/geocaching/ui/MapfileListAdapter.java | 95 +++ 23 files changed, 1604 insertions(+), 1568 deletions(-) delete mode 100644 main/src/cgeo/geocaching/CacheListAdapter.java delete mode 100644 main/src/cgeo/geocaching/cgCacheView.java delete mode 100644 main/src/cgeo/geocaching/cgCompass.java delete mode 100644 main/src/cgeo/geocaching/cgCompassMini.java delete mode 100644 main/src/cgeo/geocaching/cgDirectionImg.java delete mode 100644 main/src/cgeo/geocaching/cgDistanceView.java delete mode 100644 main/src/cgeo/geocaching/cgGPXListAdapter.java delete mode 100644 main/src/cgeo/geocaching/cgGPXView.java delete mode 100644 main/src/cgeo/geocaching/cgMapfileListAdapter.java create mode 100644 main/src/cgeo/geocaching/ui/CacheListAdapter.java create mode 100644 main/src/cgeo/geocaching/ui/CacheView.java create mode 100644 main/src/cgeo/geocaching/ui/CompassMiniView.java create mode 100644 main/src/cgeo/geocaching/ui/CompassView.java create mode 100644 main/src/cgeo/geocaching/ui/DirectionImage.java create mode 100644 main/src/cgeo/geocaching/ui/DistanceView.java create mode 100644 main/src/cgeo/geocaching/ui/GPXListAdapter.java create mode 100644 main/src/cgeo/geocaching/ui/GPXView.java create mode 100644 main/src/cgeo/geocaching/ui/MapfileListAdapter.java (limited to 'main/src') diff --git a/main/src/cgeo/geocaching/CacheListAdapter.java b/main/src/cgeo/geocaching/CacheListAdapter.java deleted file mode 100644 index a010c6d..0000000 --- a/main/src/cgeo/geocaching/CacheListAdapter.java +++ /dev/null @@ -1,832 +0,0 @@ -package cgeo.geocaching; - -import cgeo.geocaching.enumerations.CacheListType; -import cgeo.geocaching.enumerations.CacheSize; -import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.filter.IFilter; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.sorting.CacheComparator; -import cgeo.geocaching.sorting.DistanceComparator; -import cgeo.geocaching.sorting.VisitComparator; - -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; - -import android.app.Activity; -import android.content.Intent; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.drawable.Drawable; -import android.text.Spannable; -import android.text.Spanned; -import android.text.style.StrikethroughSpan; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.GestureDetector; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.AccelerateDecelerateInterpolator; -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; -import android.view.animation.AnimationSet; -import android.view.animation.TranslateAnimation; -import android.widget.ArrayAdapter; -import android.widget.CheckBox; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class CacheListAdapter extends ArrayAdapter { - - final private Resources res; - /** Resulting list of caches */ - final private List list; - private cgCacheView holder = null; - private LayoutInflater inflater = null; - private CacheComparator cacheComparator = null; - private Geopoint coords = null; - private float azimuth = 0; - private long lastSort = 0L; - private boolean sort = true; - private int checked = 0; - private boolean selectMode = false; - final private static Map gcIconDrawables = new HashMap(); - final private Set compasses = new LinkedHashSet(); - final private Set distances = new LinkedHashSet(); - final private int[] ratingBcgs = new int[3]; - final private float pixelDensity; - private static final int SWIPE_MIN_DISTANCE = 60; - private static final int SWIPE_MAX_OFF_PATH = 100; - private static final int SWIPE_DISTANCE = 80; - private static final float SWIPE_OPACITY = 0.5f; - /** - * time in milliseconds after which the list may be resorted due to position updates - */ - private static final int PAUSE_BETWEEN_LIST_SORT = 1000; - private static final String SEPARATOR = " · "; - private IFilter currentFilter = null; - private List originalList = null; - private final CacheListType cacheListType; - - public CacheListAdapter(final Activity activity, final List list, CacheListType cacheListType) { - super(activity, 0, list); - - this.res = activity.getResources(); - this.list = list; - this.cacheListType = cacheListType; - if (cacheListType == CacheListType.HISTORY) { - cacheComparator = new VisitComparator(); - } - - final DisplayMetrics metrics = new DisplayMetrics(); - activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); - pixelDensity = metrics.density; - - for (final CacheType cacheType : CacheType.values()) { - gcIconDrawables.put(cacheType, activity.getResources().getDrawable(cacheType.markerId)); - } - - if (Settings.isLightSkin()) { - ratingBcgs[0] = R.drawable.favourite_background_red_light; - ratingBcgs[1] = R.drawable.favourite_background_orange_light; - ratingBcgs[2] = R.drawable.favourite_background_green_light; - } else { - ratingBcgs[0] = R.drawable.favourite_background_red_dark; - ratingBcgs[1] = R.drawable.favourite_background_orange_dark; - ratingBcgs[2] = R.drawable.favourite_background_green_dark; - } - } - - /** - * change the sort order - * - * @param comparator - */ - public void setComparator(final CacheComparator comparator) { - cacheComparator = comparator; - forceSort(coords); - } - - public CacheComparator getCacheComparator() { - return cacheComparator; - } - - /** - * Called when a new page of caches was loaded. - */ - public void reFilter() { - if (currentFilter != null) { - // Back up the list again - originalList = new ArrayList(list); - - currentFilter.filter(list); - } - } - - /** - * Called after a user action on the filter menu. - */ - public void setFilter(final IFilter filter) { - // Backup current caches list if it isn't backed up yet - if (originalList == null) { - originalList = new ArrayList(list); - } - - // If there is already a filter in place, this is a request to change or clear the filter, so we have to - // replace the original cache list - if (currentFilter != null) { - list.clear(); - list.addAll(originalList); - } - - // Do the filtering or clear it - if (filter != null) { - filter.filter(list); - } - currentFilter = filter; - - notifyDataSetChanged(); - } - - public void clearFilter() { - if (originalList != null) { - list.clear(); - list.addAll(originalList); - - currentFilter = null; - } - - notifyDataSetChanged(); - } - - public boolean isFilter() { - return currentFilter != null; - } - - public String getFilterName() { - return currentFilter.getName(); - } - - public int getChecked() { - return checked; - } - - public boolean setSelectMode(final boolean status, final boolean clear) { - selectMode = status; - - if (!selectMode && clear) { - for (final cgCache cache : list) { - cache.setStatusChecked(false); - cache.setStatusCheckedView(false); - } - checked = 0; - } else if (selectMode) { - for (final cgCache cache : list) { - cache.setStatusCheckedView(false); - } - } - checkChecked(0); - - notifyDataSetChanged(); - - return selectMode; - } - - public boolean getSelectMode() { - return selectMode; - } - - public void switchSelectMode() { - selectMode = !selectMode; - - if (!selectMode) { - for (final cgCache cache : list) { - cache.setStatusChecked(false); - cache.setStatusCheckedView(false); - } - checked = 0; - } else { - for (final cgCache cache : list) { - cache.setStatusCheckedView(false); - } - } - checkChecked(0); - - notifyDataSetChanged(); - } - - public void invertSelection() { - int check = 0; - - for (cgCache cache : list) { - if (cache.isStatusChecked()) { - cache.setStatusChecked(false); - cache.setStatusCheckedView(false); - } else { - cache.setStatusChecked(true); - cache.setStatusCheckedView(true); - - check++; - } - } - checkChecked(check); - - notifyDataSetChanged(); - } - - public void forceSort(final Geopoint coordsIn) { - if (CollectionUtils.isEmpty(list) || !sort) { - return; - } - - if (isSortedByDistance()) { - if (coordsIn == null) { - return; - } - Collections.sort(list, new DistanceComparator(coordsIn, list)); - } - else { - Collections.sort(list, cacheComparator); - } - - notifyDataSetChanged(); - } - - public void setActualCoordinates(final Geopoint coordsIn) { - if (coordsIn == null) { - return; - } - - coords = coordsIn; - - if (CollectionUtils.isNotEmpty(list) && (System.currentTimeMillis() - lastSort) > PAUSE_BETWEEN_LIST_SORT && sort && isSortedByDistance()) { - Collections.sort(list, new DistanceComparator(coordsIn, list)); - notifyDataSetChanged(); - lastSort = System.currentTimeMillis(); - } - - for (final cgDistanceView distance : distances) { - distance.update(coordsIn); - } - - for (final cgCompassMini compass : compasses) { - compass.updateCoords(coordsIn); - } - } - - private boolean isSortedByDistance() { - return cacheComparator == null || cacheComparator instanceof DistanceComparator; - } - - public void setActualHeading(Float directionNow) { - if (directionNow == null) { - return; - } - - azimuth = directionNow; - - if (CollectionUtils.isNotEmpty(compasses)) { - for (cgCompassMini compass : compasses) { - compass.updateAzimuth(azimuth); - } - } - } - - /** - * clear all check marks - * - * @return - */ - public boolean resetChecks() { - if (list.isEmpty()) { - return false; - } - if (checked <= 0) { - return false; - } - - boolean status = getSelectMode(); - int cleared = 0; - for (cgCache cache : list) { - if (cache.isStatusChecked()) { - cache.setStatusChecked(false); - - checkChecked(-1); - cleared++; - } - } - setSelectMode(false, false); - notifyDataSetChanged(); - - return cleared > 0 || status; - } - - @Override - public View getView(final int position, final View rowView, final ViewGroup parent) { - if (inflater == null) { - inflater = ((Activity) getContext()).getLayoutInflater(); - } - - if (position > getCount()) { - Log.w(Settings.tag, "CacheListAdapter.getView: Attempt to access missing item #" + position); - return null; - } - - cgCache cache = getItem(position); - - View v = rowView; - - if (v == null) { - v = inflater.inflate(R.layout.cache, null); - - holder = new cgCacheView(); - holder.checkbox = (CheckBox) v.findViewById(R.id.checkbox); - holder.oneInfo = (RelativeLayout) v.findViewById(R.id.one_info); - holder.oneCheckbox = (RelativeLayout) v.findViewById(R.id.one_checkbox); - holder.logStatusMark = (ImageView) v.findViewById(R.id.log_status_mark); - holder.text = (TextView) v.findViewById(R.id.text); - holder.directionLayout = (RelativeLayout) v.findViewById(R.id.direction_layout); - holder.distance = (cgDistanceView) v.findViewById(R.id.distance); - holder.direction = (cgCompassMini) v.findViewById(R.id.direction); - holder.dirImgLayout = (RelativeLayout) v.findViewById(R.id.dirimg_layout); - holder.dirImg = (ImageView) v.findViewById(R.id.dirimg); - holder.inventory = (RelativeLayout) v.findViewById(R.id.inventory); - holder.favourite = (TextView) v.findViewById(R.id.favourite); - holder.info = (TextView) v.findViewById(R.id.info); - - v.setTag(holder); - } else { - holder = (cgCacheView) v.getTag(); - } - - if (cache.isOwn()) { - if (Settings.isLightSkin()) { - holder.oneInfo.setBackgroundResource(R.color.owncache_background_light); - holder.oneCheckbox.setBackgroundResource(R.color.owncache_background_light); - } else { - holder.oneInfo.setBackgroundResource(R.color.owncache_background_dark); - holder.oneCheckbox.setBackgroundResource(R.color.owncache_background_dark); - } - } else { - if (Settings.isLightSkin()) { - holder.oneInfo.setBackgroundResource(R.color.background_light); - holder.oneCheckbox.setBackgroundResource(R.color.background_light); - } else { - holder.oneInfo.setBackgroundResource(R.color.background_dark); - holder.oneCheckbox.setBackgroundResource(R.color.background_dark); - } - } - - final touchListener touchLst = new touchListener(cache.getGeocode(), cache.getName(), cache); - v.setOnClickListener(touchLst); - v.setOnLongClickListener(touchLst); - v.setOnTouchListener(touchLst); - v.setLongClickable(true); - - if (selectMode) { - if (cache.isStatusCheckedView()) { - moveRight(holder, cache, true); // move fast when already slided - } else { - moveRight(holder, cache, false); - } - } else if (cache.isStatusChecked()) { - holder.checkbox.setChecked(true); - if (cache.isStatusCheckedView()) { - moveRight(holder, cache, true); // move fast when already slided - } else { - moveRight(holder, cache, false); - } - } else { - holder.checkbox.setChecked(false); - if (cache.isStatusCheckedView()) { - moveLeft(holder, cache, false); - } else { - holder.oneInfo.clearAnimation(); - } - } - - holder.checkbox.setOnClickListener(new checkBoxListener(cache)); - - distances.add(holder.distance); - holder.distance.setContent(cache.getCoords()); - compasses.add(holder.direction); - holder.direction.setContent(cache.getCoords()); - - if (cache.isFound() && cache.isLogOffline()) { - holder.logStatusMark.setImageResource(R.drawable.mark_green_orange); - holder.logStatusMark.setVisibility(View.VISIBLE); - } else if (cache.isFound()) { - holder.logStatusMark.setImageResource(R.drawable.mark_green_more); - holder.logStatusMark.setVisibility(View.VISIBLE); - } else if (cache.isLogOffline()) { - holder.logStatusMark.setImageResource(R.drawable.mark_orange); - holder.logStatusMark.setVisibility(View.VISIBLE); - } else { - holder.logStatusMark.setVisibility(View.GONE); - } - - if (cache.getNameSp() == null) { - cache.setNameSp((new Spannable.Factory()).newSpannable(cache.getName())); - if (cache.isDisabled() || cache.isArchived()) { // strike - cache.getNameSp().setSpan(new StrikethroughSpan(), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - } - - holder.text.setText(cache.getNameSp(), TextView.BufferType.SPANNABLE); - if (gcIconDrawables.containsKey(cache.getType())) { // cache icon - holder.text.setCompoundDrawablesWithIntrinsicBounds(gcIconDrawables.get(cache.getType()), null, null, null); - } else { // unknown cache type, "mystery" icon - holder.text.setCompoundDrawablesWithIntrinsicBounds(gcIconDrawables.get(CacheType.MYSTERY), null, null, null); - } - - if (holder.inventory.getChildCount() > 0) { - holder.inventory.removeAllViews(); - } - - ImageView tbIcon = null; - if (cache.getInventoryItems() > 0) { - tbIcon = (ImageView) inflater.inflate(R.layout.trackable_icon, null); - tbIcon.setImageResource(R.drawable.trackable_all); - - holder.inventory.addView(tbIcon); - holder.inventory.setVisibility(View.VISIBLE); - } else { - holder.inventory.setVisibility(View.GONE); - } - - boolean setDiDi = false; - if (cache.getCoords() != null) { - holder.direction.setVisibility(View.VISIBLE); - holder.direction.updateAzimuth(azimuth); - if (coords != null) { - holder.distance.update(coords); - holder.direction.updateCoords(coords); - } - setDiDi = true; - } else { - if (cache.getDistance() != null) { - holder.distance.setDistance(cache.getDistance()); - setDiDi = true; - } - if (cache.getDirection() != null) { - holder.direction.setVisibility(View.VISIBLE); - holder.direction.updateAzimuth(azimuth); - holder.direction.updateHeading(cache.getDirection()); - setDiDi = true; - } - } - - if (setDiDi) { - holder.directionLayout.setVisibility(View.VISIBLE); - holder.dirImgLayout.setVisibility(View.GONE); - } else { - holder.directionLayout.setVisibility(View.GONE); - holder.distance.clear(); - - final Bitmap dirImgPre = BitmapFactory.decodeFile(cgDirectionImg.getDirectionFile(cache.getGeocode(), false).getPath()); - final Bitmap dirImg; - if (dirImgPre != null) { // null happens for invalid caches (not yet released) - dirImg = dirImgPre.copy(Bitmap.Config.ARGB_8888, true); - dirImgPre.recycle(); - } - else { - dirImg = null; - } - - if (dirImg != null) { - if (!Settings.isLightSkin()) { - int length = dirImg.getWidth() * dirImg.getHeight(); - int[] pixels = new int[length]; - dirImg.getPixels(pixels, 0, dirImg.getWidth(), 0, 0, dirImg.getWidth(), dirImg.getHeight()); - for (int i = 0; i < length; i++) { - if (pixels[i] == 0xff000000) { // replace black with white - pixels[i] = 0xffffffff; - } - } - dirImg.setPixels(pixels, 0, dirImg.getWidth(), 0, 0, dirImg.getWidth(), dirImg.getHeight()); - } - - holder.dirImg.setImageBitmap(dirImg); - holder.dirImgLayout.setVisibility(View.VISIBLE); - } else { - holder.dirImg.setImageBitmap(null); - holder.dirImgLayout.setVisibility(View.GONE); - } - } - - holder.favourite.setText(Integer.toString(cache.getFavoritePoints())); - - int favoriteBack; - // set default background, neither vote nor rating may be available - if (Settings.isLightSkin()) { - favoriteBack = R.drawable.favourite_background_light; - } else { - favoriteBack = R.drawable.favourite_background_dark; - } - float myVote = cache.getMyVote(); - if (myVote > 0) { // use my own rating for display, if I have voted - if (myVote >= 4) { - favoriteBack = ratingBcgs[2]; - } else if (myVote >= 3) { - favoriteBack = ratingBcgs[1]; - } else if (myVote > 0) { - favoriteBack = ratingBcgs[0]; - } - } else { - float rating = cache.getRating(); - if (rating >= 3.5) { - favoriteBack = ratingBcgs[2]; - } else if (rating >= 2.1) { - favoriteBack = ratingBcgs[1]; - } else if (rating > 0.0) { - favoriteBack = ratingBcgs[0]; - } - } - holder.favourite.setBackgroundResource(favoriteBack); - - if (cacheListType == CacheListType.HISTORY && cache.getVisitedDate() > 0) { - StringBuilder cacheInfo = new StringBuilder(50); - cacheInfo.append(cgBase.formatTime(cache.getVisitedDate())); - cacheInfo.append("; "); - cacheInfo.append(cgBase.formatDate(cache.getVisitedDate())); - holder.info.setText(cacheInfo.toString()); - } else { - ArrayList infos = new ArrayList(); - if (StringUtils.isNotBlank(cache.getGeocode())) { - infos.add(cache.getGeocode()); - } - if (cache.hasDifficulty()) { - infos.add("D " + String.format("%.1f", cache.getDifficulty())); - } - if (cache.hasTerrain()) { - infos.add("T " + String.format("%.1f", cache.getTerrain())); - } - - // don't show "not chosen" for events and virtuals, that should be the normal case - if (cache.getSize() != CacheSize.UNKNOWN && cache.showSize()) { - infos.add(cache.getSize().getL10n()); - } else if (cache.isEventCache() && cache.getHiddenDate() != null) { - infos.add(cgBase.formatShortDate(cache.getHiddenDate().getTime())); - } - - if (cache.isPremiumMembersOnly()) { - infos.add(res.getString(R.string.cache_premium)); - } - if (cacheListType != CacheListType.OFFLINE && cacheListType != CacheListType.HISTORY && cache.getListId() > 0) { - infos.add(res.getString(R.string.cache_offline)); - } - holder.info.setText(StringUtils.join(infos, SEPARATOR)); - } - - return v; - } - - @Override - public void notifyDataSetChanged() { - super.notifyDataSetChanged(); - - checked = 0; - for (cgCache cache : list) { - if (cache.isStatusChecked()) { - checked++; - } - } - - distances.clear(); - compasses.clear(); - } - - private class checkBoxListener implements View.OnClickListener { - - private cgCache cache = null; - - public checkBoxListener(cgCache cacheIn) { - cache = cacheIn; - } - - public void onClick(View view) { - final boolean checkNow = ((CheckBox) view).isChecked(); - - if (checkNow) { - cache.setStatusChecked(true); - checked++; - } else { - cache.setStatusChecked(false); - checked--; - } - } - } - - private class touchListener implements View.OnLongClickListener, View.OnClickListener, View.OnTouchListener { - - private String geocode = null; - private String name = null; - private cgCache cache = null; - private boolean touch = true; - private GestureDetector gestureDetector = null; - - public touchListener(String geocodeIn, String nameIn, cgCache cacheIn) { - geocode = geocodeIn; - name = nameIn; - cache = cacheIn; - - final detectGesture dGesture = new detectGesture(holder, cache); - gestureDetector = new GestureDetector(dGesture); - } - - // tap on item - public void onClick(View view) { - if (!touch) { - touch = true; - return; - } - - if (getSelectMode() || getChecked() > 0) { - return; - } - - // load cache details - Intent cachesIntent = new Intent(getContext(), CacheDetailActivity.class); - cachesIntent.putExtra("geocode", geocode); - cachesIntent.putExtra("name", name); - getContext().startActivity(cachesIntent); - } - - // long tap on item - public boolean onLongClick(View view) { - if (!touch) { - touch = true; - return true; - } - - return view.showContextMenu(); - } - - // swipe on item - public boolean onTouch(View view, MotionEvent event) { - if (gestureDetector.onTouchEvent(event)) { - touch = false; - return true; - } - - return false; - } - } - - class detectGesture extends GestureDetector.SimpleOnGestureListener { - - private cgCacheView holder = null; - private cgCache cache = null; - - public detectGesture(cgCacheView holderIn, cgCache cacheIn) { - holder = holderIn; - cache = cacheIn; - } - - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { - try { - if (getSelectMode()) { - return false; - } - - if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) { - return false; - } - - if ((e2.getX() - e1.getX()) > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > Math.abs(velocityY)) { - // left to right swipe - if (cache.isStatusChecked()) { - return true; - } - - if (holder != null && holder.oneInfo != null) { - checkChecked(+1); - holder.checkbox.setChecked(true); - cache.setStatusChecked(true); - moveRight(holder, cache, false); - } - - return true; - } else if ((e1.getX() - e2.getX()) > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > Math.abs(velocityY)) { - // right to left swipe - if (!cache.isStatusChecked()) { - return true; - } - - if (holder != null && holder.oneInfo != null) { - if (getSelectMode()) { - setSelectMode(false, false); - } - - checkChecked(-1); - holder.checkbox.setChecked(false); - cache.setStatusChecked(false); - moveLeft(holder, cache, false); - } - - return true; - } - } catch (Exception e) { - Log.w(Settings.tag, "CacheListAdapter.detectGesture.onFling: " + e.toString()); - } - - return false; - } - } - - private void checkChecked(int cnt) { - // check how many caches are selected, if any block sorting of list - checked += cnt; - sort = !(checked > 0 || getSelectMode()); - - if (sort) { - forceSort(coords); - } - } - - private void moveRight(cgCacheView holder, cgCache cache, boolean force) { - if (cache == null) { - return; - } - - holder.checkbox.setChecked(cache.isStatusChecked()); - - // slide cache info - final Animation showCheckbox = new TranslateAnimation(0, (int) (SWIPE_DISTANCE * pixelDensity), 0, 0); - showCheckbox.setRepeatCount(0); - showCheckbox.setDuration(force ? 0 : 400); - showCheckbox.setFillEnabled(true); - showCheckbox.setFillAfter(true); - showCheckbox.setInterpolator(new AccelerateDecelerateInterpolator()); - - // dim cache info - final Animation dimInfo = new AlphaAnimation(1.0f, SWIPE_OPACITY); - dimInfo.setRepeatCount(0); - dimInfo.setDuration(force ? 0 : 400); - dimInfo.setFillEnabled(true); - dimInfo.setFillAfter(true); - dimInfo.setInterpolator(new AccelerateDecelerateInterpolator()); - - // animation set (container) - final AnimationSet selectAnimation = new AnimationSet(true); - selectAnimation.setFillEnabled(true); - selectAnimation.setFillAfter(true); - - selectAnimation.addAnimation(showCheckbox); - selectAnimation.addAnimation(dimInfo); - - holder.oneInfo.startAnimation(selectAnimation); - cache.setStatusCheckedView(true); - } - - private void moveLeft(cgCacheView holder, cgCache cache, boolean force) { - if (cache == null) { - return; - } - - holder.checkbox.setChecked(cache.isStatusChecked()); - - // slide cache info - final Animation hideCheckbox = new TranslateAnimation((int) (SWIPE_DISTANCE * pixelDensity), 0, 0, 0); - hideCheckbox.setRepeatCount(0); - hideCheckbox.setDuration(force ? 0 : 400); - hideCheckbox.setFillEnabled(true); - hideCheckbox.setFillAfter(true); - hideCheckbox.setInterpolator(new AccelerateDecelerateInterpolator()); - - // brighten cache info - final Animation brightenInfo = new AlphaAnimation(SWIPE_OPACITY, 1.0f); - brightenInfo.setRepeatCount(0); - brightenInfo.setDuration(force ? 0 : 400); - brightenInfo.setFillEnabled(true); - brightenInfo.setFillAfter(true); - brightenInfo.setInterpolator(new AccelerateDecelerateInterpolator()); - - // animation set (container) - final AnimationSet selectAnimation = new AnimationSet(true); - selectAnimation.setFillEnabled(true); - selectAnimation.setFillAfter(true); - - selectAnimation.addAnimation(hideCheckbox); - selectAnimation.addAnimation(brightenInfo); - - holder.oneInfo.startAnimation(selectAnimation); - cache.setStatusCheckedView(false); - } - - public List getFilteredList() { - return list; - } -} diff --git a/main/src/cgeo/geocaching/cgBase.java b/main/src/cgeo/geocaching/cgBase.java index 18c14ff..c4a2f24 100644 --- a/main/src/cgeo/geocaching/cgBase.java +++ b/main/src/cgeo/geocaching/cgBase.java @@ -20,6 +20,7 @@ import cgeo.geocaching.geopoint.IConversion; import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.network.HtmlImage; import cgeo.geocaching.twitter.Twitter; +import cgeo.geocaching.ui.DirectionImage; import cgeo.geocaching.utils.BaseUtils; import cgeo.geocaching.utils.CancellableHandler; @@ -657,7 +658,7 @@ public class cgBase { { for (cgCache oneCache : parseResult.cacheList) { if (oneCache.getCoords() == null && StringUtils.isNotEmpty(oneCache.getDirectionImg())) { - cgDirectionImg.getDrawable(oneCache.getGeocode(), oneCache.getDirectionImg()); + DirectionImage.getDrawable(oneCache.getGeocode(), oneCache.getDirectionImg()); } } } diff --git a/main/src/cgeo/geocaching/cgCacheView.java b/main/src/cgeo/geocaching/cgCacheView.java deleted file mode 100644 index 39f5a45..0000000 --- a/main/src/cgeo/geocaching/cgCacheView.java +++ /dev/null @@ -1,23 +0,0 @@ -package cgeo.geocaching; - -import android.widget.CheckBox; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.TextView; - -public class cgCacheView { - // layouts & views - public RelativeLayout oneInfo; - public RelativeLayout oneCheckbox; - public CheckBox checkbox; - public ImageView logStatusMark; - public TextView text; - public TextView favourite; - public TextView info; - public RelativeLayout inventory; - public RelativeLayout directionLayout; - public cgDistanceView distance; - public cgCompassMini direction; - public RelativeLayout dirImgLayout; - public ImageView dirImg; -} diff --git a/main/src/cgeo/geocaching/cgCompass.java b/main/src/cgeo/geocaching/cgCompass.java deleted file mode 100644 index aa4466b..0000000 --- a/main/src/cgeo/geocaching/cgCompass.java +++ /dev/null @@ -1,288 +0,0 @@ -package cgeo.geocaching; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.PaintFlagsDrawFilter; -import android.os.Handler; -import android.os.Message; -import android.util.AttributeSet; -import android.util.Log; -import android.view.View; - -public class cgCompass extends View { - - private changeThread watchdog = null; - private volatile boolean wantStop = false; - private Context context = null; - private Bitmap compassUnderlay = null; - private Bitmap compassRose = null; - private Bitmap compassArrow = null; - private Bitmap compassOverlay = null; - /** - * North direction currently SHOWN on compass (not measured) - */ - private double azimuthShown = 0.0; - /** - * cache direction currently SHOWN on compass (not measured) - */ - private double cacheHeadingShown = 0.0; - /** - * cache direction measured from device, or 0.0 - */ - private double cacheHeadingMeasured = 0.0; - /** - * North direction measured from device, or 0.0 - */ - private double northMeasured = 0.0; - private PaintFlagsDrawFilter setfil = null; - private PaintFlagsDrawFilter remfil = null; - private int compassUnderlayWidth = 0; - private int compassUnderlayHeight = 0; - private int compassRoseWidth = 0; - private int compassRoseHeight = 0; - private int compassArrowWidth = 0; - private int compassArrowHeight = 0; - private int compassOverlayWidth = 0; - private int compassOverlayHeight = 0; - private boolean initialDisplay; - private Handler changeHandler = new Handler() { - - @Override - public void handleMessage(Message message) { - try { - invalidate(); - } catch (Exception e) { - Log.e(Settings.tag, "cgCompass.changeHandler: " + e.toString()); - } - } - }; - - public cgCompass(Context contextIn) { - super(contextIn); - context = contextIn; - } - - public cgCompass(Context contextIn, AttributeSet attrs) { - super(contextIn, attrs); - context = contextIn; - } - - @Override - public void onAttachedToWindow() { - compassUnderlay = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_underlay); - compassRose = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_rose); - compassArrow = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_arrow); - compassOverlay = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_overlay); - - compassUnderlayWidth = compassUnderlay.getWidth(); - compassUnderlayHeight = compassUnderlay.getWidth(); - compassRoseWidth = compassRose.getWidth(); - compassRoseHeight = compassRose.getWidth(); - compassArrowWidth = compassArrow.getWidth(); - compassArrowHeight = compassArrow.getWidth(); - compassOverlayWidth = compassOverlay.getWidth(); - compassOverlayHeight = compassOverlay.getWidth(); - - setfil = new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG); - remfil = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0); - - initialDisplay = true; - wantStop = false; - - watchdog = new changeThread(); - watchdog.start(); - } - - @Override - public void onDetachedFromWindow() { - wantStop = true; - - if (compassUnderlay != null) { - compassUnderlay.recycle(); - } - - if (compassRose != null) { - compassRose.recycle(); - } - - if (compassArrow != null) { - compassArrow.recycle(); - } - - if (compassOverlay != null) { - compassOverlay.recycle(); - } - } - - protected synchronized void updateNorth(double northHeadingIn, double cacheHeadingIn) { - if (initialDisplay) { - // We will force the compass to move brutally if this is the first - // update since it is visible. - azimuthShown = northHeadingIn; - cacheHeadingShown = cacheHeadingIn; - - // it may take some time to get an initial direction measurement for the device - if (northHeadingIn != 0.0) { - initialDisplay = false; - } - } - northMeasured = northHeadingIn; - cacheHeadingMeasured = cacheHeadingIn; - } - - /** - * Compute the new value, moving by small increments. - * - * @param goal - * the goal to reach - * @param actual - * the actual value - * @return the new value - */ - static protected double smoothUpdate(double goal, double actual) { - double diff = goal - actual; - final boolean largeDiff = Math.abs(diff) > 5; - - double offset = 0.0; - - if (diff < 0.0) { - diff += 360.0; - } else if (diff >= 360.0) { - diff -= 360.0; - } - - // If the difference is smaller than 1 degree, do nothing as it - // causes the arrow to vibrate. - if (diff > 1.0 && diff <= 180.0) { - offset = largeDiff ? 2.0 : 1.0; - } else if (diff > 180.0 && diff < 359.0) { - offset = largeDiff ? -2.0 : -1.0; - } - - return actual + offset; - } - - private class changeThread extends Thread { - - @Override - public void run() { - while (!wantStop) { - try { - sleep(50); - } catch (Exception e) { - // nothing - } - - synchronized (cgCompass.this) { - azimuthShown = smoothUpdate(northMeasured, azimuthShown); - cacheHeadingShown = smoothUpdate(cacheHeadingMeasured, cacheHeadingShown); - } - - changeHandler.sendMessage(new Message()); - } - } - } - - @Override - protected void onDraw(Canvas canvas) { - // use local synchronized variables to avoid them being changed from the device during drawing - double azimuthDrawn; - double headingDrawn; - - synchronized (this) { - azimuthDrawn = azimuthShown; - headingDrawn = cacheHeadingShown; - } - - double azimuthTemp = azimuthDrawn; - double azimuthRelative = azimuthTemp - headingDrawn; - if (azimuthRelative < 0) { - azimuthRelative += 360; - } else if (azimuthRelative >= 360) { - azimuthRelative -= 360; - } - - // compass margins - int canvasCenterX = (compassRoseWidth / 2) + ((getWidth() - compassRoseWidth) / 2); - int canvasCenterY = (compassRoseHeight / 2) + ((getHeight() - compassRoseHeight) / 2); - - int marginLeftTemp = 0; - int marginTopTemp = 0; - - super.onDraw(canvas); - - canvas.save(); - canvas.setDrawFilter(setfil); - - marginLeftTemp = (getWidth() - compassUnderlayWidth) / 2; - marginTopTemp = (getHeight() - compassUnderlayHeight) / 2; - - canvas.drawBitmap(compassUnderlay, marginLeftTemp, marginTopTemp, null); - - marginLeftTemp = (getWidth() - compassRoseWidth) / 2; - marginTopTemp = (getHeight() - compassRoseHeight) / 2; - - canvas.rotate((float) -azimuthTemp, canvasCenterX, canvasCenterY); - canvas.drawBitmap(compassRose, marginLeftTemp, marginTopTemp, null); - canvas.rotate((float) azimuthTemp, canvasCenterX, canvasCenterY); - - marginLeftTemp = (getWidth() - compassArrowWidth) / 2; - marginTopTemp = (getHeight() - compassArrowHeight) / 2; - - canvas.rotate((float) -azimuthRelative, canvasCenterX, canvasCenterY); - canvas.drawBitmap(compassArrow, marginLeftTemp, marginTopTemp, null); - canvas.rotate((float) azimuthRelative, canvasCenterX, canvasCenterY); - - marginLeftTemp = (getWidth() - compassOverlayWidth) / 2; - marginTopTemp = (getHeight() - compassOverlayHeight) / 2; - - canvas.drawBitmap(compassOverlay, marginLeftTemp, marginTopTemp, null); - - canvas.setDrawFilter(remfil); - canvas.restore(); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); - } - - private int measureWidth(int measureSpec) { - int result = 0; - int specMode = MeasureSpec.getMode(measureSpec); - int specSize = MeasureSpec.getSize(measureSpec); - - if (specMode == MeasureSpec.EXACTLY) { - result = specSize; - } else { - result = compassArrow.getWidth() + getPaddingLeft() + getPaddingRight(); - - if (specMode == MeasureSpec.AT_MOST) { - result = Math.min(result, specSize); - } - } - - return result; - } - - private int measureHeight(int measureSpec) { - int result = 0; - int specMode = MeasureSpec.getMode(measureSpec); - int specSize = MeasureSpec.getSize(measureSpec); - - if (specMode == MeasureSpec.EXACTLY) { - result = specSize; - } else { - result = compassArrow.getHeight() + getPaddingTop() + getPaddingBottom(); - - if (specMode == MeasureSpec.AT_MOST) { - result = Math.min(result, specSize); - } - } - - return result; - } -} \ No newline at end of file diff --git a/main/src/cgeo/geocaching/cgCompassMini.java b/main/src/cgeo/geocaching/cgCompassMini.java deleted file mode 100644 index 4682502..0000000 --- a/main/src/cgeo/geocaching/cgCompassMini.java +++ /dev/null @@ -1,172 +0,0 @@ -package cgeo.geocaching; - -import cgeo.geocaching.geopoint.Geopoint; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.PaintFlagsDrawFilter; -import android.util.AttributeSet; -import android.view.View; - -public class cgCompassMini extends View { - private int arrowSkin = R.drawable.compass_arrow_mini_white; - private Context context = null; - private Geopoint cacheCoords = null; - private Bitmap compassArrow = null; - private float azimuth = 0; - private float heading = 0; - private PaintFlagsDrawFilter setfil = null; - private PaintFlagsDrawFilter remfil = null; - - public cgCompassMini(Context contextIn) { - super(contextIn); - context = contextIn; - } - - public cgCompassMini(Context contextIn, AttributeSet attrs) { - super(contextIn, attrs); - context = contextIn; - - TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.cgCompassMini); - int usedSkin = attributes.getInt(R.styleable.cgCompassMini_skin, 0); - if (usedSkin == 1) { - arrowSkin = R.drawable.compass_arrow_mini_black; - } else { - arrowSkin = R.drawable.compass_arrow_mini_white; - } - } - - @Override - public void onAttachedToWindow() { - compassArrow = BitmapFactory.decodeResource(context.getResources(), arrowSkin); - - setfil = new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG); - remfil = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0); - } - - @Override - public void onDetachedFromWindow() { - if (compassArrow != null) { - compassArrow.recycle(); - compassArrow = null; - } - } - - public void setContent(final Geopoint cacheCoordsIn) { - cacheCoords = cacheCoordsIn; - } - - protected void updateAzimuth(float azimuthIn) { - azimuth = azimuthIn; - - updateDirection(); - } - - protected void updateHeading(float headingIn) { - heading = headingIn; - - updateDirection(); - } - - protected void updateCoords(final Geopoint coordsIn) { - if (coordsIn == null || cacheCoords == null) { - return; - } - - heading = coordsIn.bearingTo(cacheCoords); - - updateDirection(); - } - - protected void updateDirection() { - if (compassArrow == null || compassArrow.isRecycled()) { - return; - } - - // compass margins - int compassRoseWidth = compassArrow.getWidth(); - int compassRoseHeight = compassArrow.getWidth(); - int marginLeft = (getWidth() - compassRoseWidth) / 2; - int marginTop = (getHeight() - compassRoseHeight) / 2; - - invalidate(marginLeft, marginTop, (marginLeft + compassRoseWidth), (marginTop + compassRoseHeight)); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - float azimuthRelative = azimuth - heading; - if (azimuthRelative < 0) { - azimuthRelative += 360; - } else if (azimuthRelative >= 360) { - azimuthRelative -= 360; - } - - // compass margins - canvas.setDrawFilter(setfil); - - int marginLeft = 0; - int marginTop = 0; - - int compassArrowWidth = compassArrow.getWidth(); - int compassArrowHeight = compassArrow.getWidth(); - - int canvasCenterX = (compassArrowWidth / 2) + ((getWidth() - compassArrowWidth) / 2); - int canvasCenterY = (compassArrowHeight / 2) + ((getHeight() - compassArrowHeight) / 2); - - marginLeft = (getWidth() - compassArrowWidth) / 2; - marginTop = (getHeight() - compassArrowHeight) / 2; - - canvas.rotate(-azimuthRelative, canvasCenterX, canvasCenterY); - canvas.drawBitmap(compassArrow, marginLeft, marginTop, null); - canvas.rotate(azimuthRelative, canvasCenterX, canvasCenterY); - - canvas.setDrawFilter(remfil); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); - } - - private int measureWidth(int measureSpec) { - int result = 0; - int specMode = MeasureSpec.getMode(measureSpec); - int specSize = MeasureSpec.getSize(measureSpec); - - if (specMode == MeasureSpec.EXACTLY) { - result = specSize; - } else { - result = 21 + getPaddingLeft() + getPaddingRight(); - - if (specMode == MeasureSpec.AT_MOST) { - result = Math.min(result, specSize); - } - } - - return result; - } - - private int measureHeight(int measureSpec) { - int result = 0; - int specMode = MeasureSpec.getMode(measureSpec); - int specSize = MeasureSpec.getSize(measureSpec); - - if (specMode == MeasureSpec.EXACTLY) { - result = specSize; - } else { - result = 21 + getPaddingTop() + getPaddingBottom(); - - if (specMode == MeasureSpec.AT_MOST) { - result = Math.min(result, specSize); - } - } - - return result; - } -} \ No newline at end of file diff --git a/main/src/cgeo/geocaching/cgDirectionImg.java b/main/src/cgeo/geocaching/cgDirectionImg.java deleted file mode 100644 index 7b28bf2..0000000 --- a/main/src/cgeo/geocaching/cgDirectionImg.java +++ /dev/null @@ -1,28 +0,0 @@ -package cgeo.geocaching; - -import cgeo.geocaching.files.LocalStorage; - -import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpResponse; - -import java.io.File; - -public class cgDirectionImg { - - public static void getDrawable(final String geocode, final String code) { - if (StringUtils.isBlank(geocode) || StringUtils.isBlank(code)) { - return; - } - - final HttpResponse httpResponse = - cgBase.request("http://www.geocaching.com/ImgGen/seek/CacheDir.ashx", new Parameters("k", code), false); - if (httpResponse != null) { - LocalStorage.saveEntityToFile(httpResponse.getEntity(), getDirectionFile(geocode, true)); - } - } - - public static File getDirectionFile(final String geocode, final boolean createDirs) { - return LocalStorage.getStorageFile(geocode, "direction.png", false, createDirs); - } - -} \ No newline at end of file diff --git a/main/src/cgeo/geocaching/cgDistanceView.java b/main/src/cgeo/geocaching/cgDistanceView.java deleted file mode 100644 index 704a655..0000000 --- a/main/src/cgeo/geocaching/cgDistanceView.java +++ /dev/null @@ -1,42 +0,0 @@ -package cgeo.geocaching; - -import cgeo.geocaching.geopoint.Geopoint; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.TextView; - -public class cgDistanceView extends TextView { - private Geopoint cacheCoords = null; - - public cgDistanceView(Context context) { - super(context); - } - - public cgDistanceView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public cgDistanceView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - public void setContent(final Geopoint cacheCoordsIn) { - cacheCoords = cacheCoordsIn; - } - - public void update(final Geopoint coords) { - if (cacheCoords == null || coords == null) { - return; - } - setText(cgBase.getHumanDistance(coords.distanceTo(cacheCoords))); - } - - public void setDistance(Float distance) { - setText("~" + cgBase.getHumanDistance(distance)); - } - - public void clear() { - setText(null); - } -} \ No newline at end of file diff --git a/main/src/cgeo/geocaching/cgGPXListAdapter.java b/main/src/cgeo/geocaching/cgGPXListAdapter.java deleted file mode 100644 index 7b163cf..0000000 --- a/main/src/cgeo/geocaching/cgGPXListAdapter.java +++ /dev/null @@ -1,76 +0,0 @@ -package cgeo.geocaching; - -import cgeo.geocaching.files.GPXImporter; - -import android.app.Activity; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.TextView; - -import java.io.File; -import java.util.List; - -public class cgGPXListAdapter extends ArrayAdapter { - private cgGPXView holder = null; - private cgeogpxes parent = null; - private LayoutInflater inflater = null; - - public cgGPXListAdapter(cgeogpxes parentIn, List listIn) { - super(parentIn, 0, listIn); - - parent = parentIn; - } - - @Override - public View getView(final int position, final View rowView, final ViewGroup parent) { - if (inflater == null) { - inflater = ((Activity) getContext()).getLayoutInflater(); - } - - if (position > getCount()) { - Log.w(Settings.tag, "cgGPXListAdapter.getView: Attempt to access missing item #" + position); - return null; - } - - File file = getItem(position); - - View v = rowView; - - if (v == null) { - v = inflater.inflate(R.layout.gpx_item, null); - - holder = new cgGPXView(); - holder.filepath = (TextView) v.findViewById(R.id.filepath); - holder.filename = (TextView) v.findViewById(R.id.filename); - - v.setTag(holder); - } else { - holder = (cgGPXView) v.getTag(); - } - - final touchListener touchLst = new touchListener(file); - v.setOnClickListener(touchLst); - - holder.filepath.setText(file.getParent()); - holder.filename.setText(file.getName()); - - return v; - } - - private class touchListener implements View.OnClickListener { - private File file = null; - - public touchListener(File fileIn) { - file = fileIn; - } - - // tap on item - @Override - public void onClick(View view) { - (new GPXImporter(parent, parent.getListId(), null)).importGPX(file); - } - } -} diff --git a/main/src/cgeo/geocaching/cgGPXView.java b/main/src/cgeo/geocaching/cgGPXView.java deleted file mode 100644 index a731f70..0000000 --- a/main/src/cgeo/geocaching/cgGPXView.java +++ /dev/null @@ -1,9 +0,0 @@ -package cgeo.geocaching; - -import android.widget.TextView; - -public class cgGPXView { - // layouts & views - public TextView filepath; - public TextView filename; -} diff --git a/main/src/cgeo/geocaching/cgMapfileListAdapter.java b/main/src/cgeo/geocaching/cgMapfileListAdapter.java deleted file mode 100644 index 5294ff2..0000000 --- a/main/src/cgeo/geocaching/cgMapfileListAdapter.java +++ /dev/null @@ -1,89 +0,0 @@ -package cgeo.geocaching; - -import android.app.Activity; -import android.graphics.Typeface; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.TextView; - -import java.io.File; -import java.util.List; - -public class cgMapfileListAdapter extends ArrayAdapter { - - private cgSelectMapfile parentView; - private LayoutInflater inflater; - private MapfileView holder; - - public cgMapfileListAdapter(cgSelectMapfile parentIn, List listIn) { - super(parentIn, 0, listIn); - - parentView = parentIn; - } - - @Override - public View getView(final int position, final View rowView, final ViewGroup parent) { - if (inflater == null) { - inflater = ((Activity) getContext()).getLayoutInflater(); - } - - if (position > getCount()) { - Log.w(Settings.tag, "cgGPXListAdapter.getView: Attempt to access missing item #" + position); - return null; - } - - File file = getItem(position); - - View v = rowView; - - if (v == null) { - v = inflater.inflate(R.layout.mapfile_item, null); - - holder = new MapfileView(); - holder.filepath = (TextView) v.findViewById(R.id.mapfilepath); - holder.filename = (TextView) v.findViewById(R.id.mapfilename); - - v.setTag(holder); - } else { - holder = (MapfileView) v.getTag(); - } - - File current = new File(parentView.getCurrentMapfile()); - - if (file.equals(current)) { - holder.filename.setTypeface(holder.filename.getTypeface(), Typeface.BOLD); - } else { - holder.filename.setTypeface(holder.filename.getTypeface(), Typeface.NORMAL); - } - - final touchListener touchLst = new touchListener(file); - v.setOnClickListener(touchLst); - - holder.filepath.setText(file.getParent()); - holder.filename.setText(file.getName()); - - return v; - } - - private class touchListener implements View.OnClickListener { - private File file = null; - - public touchListener(File fileIn) { - file = fileIn; - } - - // tap on item - public void onClick(View view) { - parentView.setMapfile(file.toString()); - parentView.close(); - } - } - - private static class MapfileView { - public TextView filepath; - public TextView filename; - } -} diff --git a/main/src/cgeo/geocaching/cgSelectMapfile.java b/main/src/cgeo/geocaching/cgSelectMapfile.java index eebd2c9..b97d717 100644 --- a/main/src/cgeo/geocaching/cgSelectMapfile.java +++ b/main/src/cgeo/geocaching/cgSelectMapfile.java @@ -2,6 +2,7 @@ package cgeo.geocaching; import cgeo.geocaching.files.FileList; import cgeo.geocaching.files.LocalStorage; +import cgeo.geocaching.ui.MapfileListAdapter; import android.content.Intent; import android.os.Bundle; @@ -10,7 +11,7 @@ import android.os.Environment; import java.io.File; import java.util.List; -public class cgSelectMapfile extends FileList { +public class cgSelectMapfile extends FileList { public cgSelectMapfile() { super("map"); @@ -35,8 +36,8 @@ public class cgSelectMapfile extends FileList { } @Override - protected cgMapfileListAdapter getAdapter(List files) { - return new cgMapfileListAdapter(this, files); + protected MapfileListAdapter getAdapter(List files) { + return new MapfileListAdapter(this, files); } @Override diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index 599f480..aa90336 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -31,6 +31,7 @@ import cgeo.geocaching.sorting.StateComparator; import cgeo.geocaching.sorting.TerrainComparator; import cgeo.geocaching.sorting.VisitComparator; import cgeo.geocaching.sorting.VoteComparator; +import cgeo.geocaching.ui.CacheListAdapter; import cgeo.geocaching.utils.RunnableWithArgument; import org.apache.commons.collections.CollectionUtils; diff --git a/main/src/cgeo/geocaching/cgeogpxes.java b/main/src/cgeo/geocaching/cgeogpxes.java index cb8167a..ab903ec 100644 --- a/main/src/cgeo/geocaching/cgeogpxes.java +++ b/main/src/cgeo/geocaching/cgeogpxes.java @@ -4,6 +4,7 @@ import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; import cgeo.geocaching.files.FileList; import cgeo.geocaching.files.GPXImporter; +import cgeo.geocaching.ui.GPXListAdapter; import org.apache.commons.lang3.StringUtils; @@ -15,7 +16,7 @@ import android.os.Environment; import java.io.File; import java.util.List; -public class cgeogpxes extends FileList { +public class cgeogpxes extends FileList { private static final String EXTRAS_LIST_ID = "list"; public cgeogpxes() { @@ -25,8 +26,8 @@ public class cgeogpxes extends FileList { private int listId = 1; @Override - protected cgGPXListAdapter getAdapter(List files) { - return new cgGPXListAdapter(this, files); + protected GPXListAdapter getAdapter(List files) { + return new GPXListAdapter(this, files); } @Override diff --git a/main/src/cgeo/geocaching/cgeonavigate.java b/main/src/cgeo/geocaching/cgeonavigate.java index 45bdf43..519521d 100644 --- a/main/src/cgeo/geocaching/cgeonavigate.java +++ b/main/src/cgeo/geocaching/cgeonavigate.java @@ -3,6 +3,7 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.maps.CGeoMap; +import cgeo.geocaching.ui.CompassView; import org.apache.commons.lang3.StringUtils; @@ -48,7 +49,7 @@ public class cgeonavigate extends AbstractActivity { private TextView navLocation = null; private TextView distanceView = null; private TextView headingView = null; - private cgCompass compassView = null; + private CompassView compassView = null; private updaterThread updater = null; private Handler updaterHandler = new Handler() { @@ -124,7 +125,7 @@ public class cgeonavigate extends AbstractActivity { } // get textviews once - compassView = (cgCompass) findViewById(R.id.rose); + compassView = (CompassView) findViewById(R.id.rose); // start updater thread updater = new updaterThread(updaterHandler); diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java new file mode 100644 index 0000000..c2910cf --- /dev/null +++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java @@ -0,0 +1,842 @@ +package cgeo.geocaching.ui; + +import cgeo.geocaching.CacheDetailActivity; +import cgeo.geocaching.R; +import cgeo.geocaching.Settings; +import cgeo.geocaching.cgBase; +import cgeo.geocaching.cgCache; +import cgeo.geocaching.R.color; +import cgeo.geocaching.R.drawable; +import cgeo.geocaching.R.id; +import cgeo.geocaching.R.layout; +import cgeo.geocaching.R.string; +import cgeo.geocaching.enumerations.CacheListType; +import cgeo.geocaching.enumerations.CacheSize; +import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.filter.IFilter; +import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.sorting.CacheComparator; +import cgeo.geocaching.sorting.DistanceComparator; +import cgeo.geocaching.sorting.VisitComparator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; + +import android.app.Activity; +import android.content.Intent; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.Drawable; +import android.text.Spannable; +import android.text.Spanned; +import android.text.style.StrikethroughSpan; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.GestureDetector; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.view.animation.AnimationSet; +import android.view.animation.TranslateAnimation; +import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class CacheListAdapter extends ArrayAdapter { + + final private Resources res; + /** Resulting list of caches */ + final private List list; + private CacheView holder = null; + private LayoutInflater inflater = null; + private CacheComparator cacheComparator = null; + private Geopoint coords = null; + private float azimuth = 0; + private long lastSort = 0L; + private boolean sort = true; + private int checked = 0; + private boolean selectMode = false; + final private static Map gcIconDrawables = new HashMap(); + final private Set compasses = new LinkedHashSet(); + final private Set distances = new LinkedHashSet(); + final private int[] ratingBcgs = new int[3]; + final private float pixelDensity; + private static final int SWIPE_MIN_DISTANCE = 60; + private static final int SWIPE_MAX_OFF_PATH = 100; + private static final int SWIPE_DISTANCE = 80; + private static final float SWIPE_OPACITY = 0.5f; + /** + * time in milliseconds after which the list may be resorted due to position updates + */ + private static final int PAUSE_BETWEEN_LIST_SORT = 1000; + private static final String SEPARATOR = " · "; + private IFilter currentFilter = null; + private List originalList = null; + private final CacheListType cacheListType; + + public CacheListAdapter(final Activity activity, final List list, CacheListType cacheListType) { + super(activity, 0, list); + + this.res = activity.getResources(); + this.list = list; + this.cacheListType = cacheListType; + if (cacheListType == CacheListType.HISTORY) { + cacheComparator = new VisitComparator(); + } + + final DisplayMetrics metrics = new DisplayMetrics(); + activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); + pixelDensity = metrics.density; + + for (final CacheType cacheType : CacheType.values()) { + gcIconDrawables.put(cacheType, activity.getResources().getDrawable(cacheType.markerId)); + } + + if (Settings.isLightSkin()) { + ratingBcgs[0] = R.drawable.favourite_background_red_light; + ratingBcgs[1] = R.drawable.favourite_background_orange_light; + ratingBcgs[2] = R.drawable.favourite_background_green_light; + } else { + ratingBcgs[0] = R.drawable.favourite_background_red_dark; + ratingBcgs[1] = R.drawable.favourite_background_orange_dark; + ratingBcgs[2] = R.drawable.favourite_background_green_dark; + } + } + + /** + * change the sort order + * + * @param comparator + */ + public void setComparator(final CacheComparator comparator) { + cacheComparator = comparator; + forceSort(coords); + } + + public CacheComparator getCacheComparator() { + return cacheComparator; + } + + /** + * Called when a new page of caches was loaded. + */ + public void reFilter() { + if (currentFilter != null) { + // Back up the list again + originalList = new ArrayList(list); + + currentFilter.filter(list); + } + } + + /** + * Called after a user action on the filter menu. + */ + public void setFilter(final IFilter filter) { + // Backup current caches list if it isn't backed up yet + if (originalList == null) { + originalList = new ArrayList(list); + } + + // If there is already a filter in place, this is a request to change or clear the filter, so we have to + // replace the original cache list + if (currentFilter != null) { + list.clear(); + list.addAll(originalList); + } + + // Do the filtering or clear it + if (filter != null) { + filter.filter(list); + } + currentFilter = filter; + + notifyDataSetChanged(); + } + + public void clearFilter() { + if (originalList != null) { + list.clear(); + list.addAll(originalList); + + currentFilter = null; + } + + notifyDataSetChanged(); + } + + public boolean isFilter() { + return currentFilter != null; + } + + public String getFilterName() { + return currentFilter.getName(); + } + + public int getChecked() { + return checked; + } + + public boolean setSelectMode(final boolean status, final boolean clear) { + selectMode = status; + + if (!selectMode && clear) { + for (final cgCache cache : list) { + cache.setStatusChecked(false); + cache.setStatusCheckedView(false); + } + checked = 0; + } else if (selectMode) { + for (final cgCache cache : list) { + cache.setStatusCheckedView(false); + } + } + checkChecked(0); + + notifyDataSetChanged(); + + return selectMode; + } + + public boolean getSelectMode() { + return selectMode; + } + + public void switchSelectMode() { + selectMode = !selectMode; + + if (!selectMode) { + for (final cgCache cache : list) { + cache.setStatusChecked(false); + cache.setStatusCheckedView(false); + } + checked = 0; + } else { + for (final cgCache cache : list) { + cache.setStatusCheckedView(false); + } + } + checkChecked(0); + + notifyDataSetChanged(); + } + + public void invertSelection() { + int check = 0; + + for (cgCache cache : list) { + if (cache.isStatusChecked()) { + cache.setStatusChecked(false); + cache.setStatusCheckedView(false); + } else { + cache.setStatusChecked(true); + cache.setStatusCheckedView(true); + + check++; + } + } + checkChecked(check); + + notifyDataSetChanged(); + } + + public void forceSort(final Geopoint coordsIn) { + if (CollectionUtils.isEmpty(list) || !sort) { + return; + } + + if (isSortedByDistance()) { + if (coordsIn == null) { + return; + } + Collections.sort(list, new DistanceComparator(coordsIn, list)); + } + else { + Collections.sort(list, cacheComparator); + } + + notifyDataSetChanged(); + } + + public void setActualCoordinates(final Geopoint coordsIn) { + if (coordsIn == null) { + return; + } + + coords = coordsIn; + + if (CollectionUtils.isNotEmpty(list) && (System.currentTimeMillis() - lastSort) > PAUSE_BETWEEN_LIST_SORT && sort && isSortedByDistance()) { + Collections.sort(list, new DistanceComparator(coordsIn, list)); + notifyDataSetChanged(); + lastSort = System.currentTimeMillis(); + } + + for (final DistanceView distance : distances) { + distance.update(coordsIn); + } + + for (final CompassMiniView compass : compasses) { + compass.updateCoords(coordsIn); + } + } + + private boolean isSortedByDistance() { + return cacheComparator == null || cacheComparator instanceof DistanceComparator; + } + + public void setActualHeading(Float directionNow) { + if (directionNow == null) { + return; + } + + azimuth = directionNow; + + if (CollectionUtils.isNotEmpty(compasses)) { + for (CompassMiniView compass : compasses) { + compass.updateAzimuth(azimuth); + } + } + } + + /** + * clear all check marks + * + * @return + */ + public boolean resetChecks() { + if (list.isEmpty()) { + return false; + } + if (checked <= 0) { + return false; + } + + boolean status = getSelectMode(); + int cleared = 0; + for (cgCache cache : list) { + if (cache.isStatusChecked()) { + cache.setStatusChecked(false); + + checkChecked(-1); + cleared++; + } + } + setSelectMode(false, false); + notifyDataSetChanged(); + + return cleared > 0 || status; + } + + @Override + public View getView(final int position, final View rowView, final ViewGroup parent) { + if (inflater == null) { + inflater = ((Activity) getContext()).getLayoutInflater(); + } + + if (position > getCount()) { + Log.w(Settings.tag, "CacheListAdapter.getView: Attempt to access missing item #" + position); + return null; + } + + cgCache cache = getItem(position); + + View v = rowView; + + if (v == null) { + v = inflater.inflate(R.layout.cache, null); + + holder = new CacheView(); + holder.checkbox = (CheckBox) v.findViewById(R.id.checkbox); + holder.oneInfo = (RelativeLayout) v.findViewById(R.id.one_info); + holder.oneCheckbox = (RelativeLayout) v.findViewById(R.id.one_checkbox); + holder.logStatusMark = (ImageView) v.findViewById(R.id.log_status_mark); + holder.text = (TextView) v.findViewById(R.id.text); + holder.directionLayout = (RelativeLayout) v.findViewById(R.id.direction_layout); + holder.distance = (DistanceView) v.findViewById(R.id.distance); + holder.direction = (CompassMiniView) v.findViewById(R.id.direction); + holder.dirImgLayout = (RelativeLayout) v.findViewById(R.id.dirimg_layout); + holder.dirImg = (ImageView) v.findViewById(R.id.dirimg); + holder.inventory = (RelativeLayout) v.findViewById(R.id.inventory); + holder.favourite = (TextView) v.findViewById(R.id.favourite); + holder.info = (TextView) v.findViewById(R.id.info); + + v.setTag(holder); + } else { + holder = (CacheView) v.getTag(); + } + + if (cache.isOwn()) { + if (Settings.isLightSkin()) { + holder.oneInfo.setBackgroundResource(R.color.owncache_background_light); + holder.oneCheckbox.setBackgroundResource(R.color.owncache_background_light); + } else { + holder.oneInfo.setBackgroundResource(R.color.owncache_background_dark); + holder.oneCheckbox.setBackgroundResource(R.color.owncache_background_dark); + } + } else { + if (Settings.isLightSkin()) { + holder.oneInfo.setBackgroundResource(R.color.background_light); + holder.oneCheckbox.setBackgroundResource(R.color.background_light); + } else { + holder.oneInfo.setBackgroundResource(R.color.background_dark); + holder.oneCheckbox.setBackgroundResource(R.color.background_dark); + } + } + + final touchListener touchLst = new touchListener(cache.getGeocode(), cache.getName(), cache); + v.setOnClickListener(touchLst); + v.setOnLongClickListener(touchLst); + v.setOnTouchListener(touchLst); + v.setLongClickable(true); + + if (selectMode) { + if (cache.isStatusCheckedView()) { + moveRight(holder, cache, true); // move fast when already slided + } else { + moveRight(holder, cache, false); + } + } else if (cache.isStatusChecked()) { + holder.checkbox.setChecked(true); + if (cache.isStatusCheckedView()) { + moveRight(holder, cache, true); // move fast when already slided + } else { + moveRight(holder, cache, false); + } + } else { + holder.checkbox.setChecked(false); + if (cache.isStatusCheckedView()) { + moveLeft(holder, cache, false); + } else { + holder.oneInfo.clearAnimation(); + } + } + + holder.checkbox.setOnClickListener(new checkBoxListener(cache)); + + distances.add(holder.distance); + holder.distance.setContent(cache.getCoords()); + compasses.add(holder.direction); + holder.direction.setContent(cache.getCoords()); + + if (cache.isFound() && cache.isLogOffline()) { + holder.logStatusMark.setImageResource(R.drawable.mark_green_orange); + holder.logStatusMark.setVisibility(View.VISIBLE); + } else if (cache.isFound()) { + holder.logStatusMark.setImageResource(R.drawable.mark_green_more); + holder.logStatusMark.setVisibility(View.VISIBLE); + } else if (cache.isLogOffline()) { + holder.logStatusMark.setImageResource(R.drawable.mark_orange); + holder.logStatusMark.setVisibility(View.VISIBLE); + } else { + holder.logStatusMark.setVisibility(View.GONE); + } + + if (cache.getNameSp() == null) { + cache.setNameSp((new Spannable.Factory()).newSpannable(cache.getName())); + if (cache.isDisabled() || cache.isArchived()) { // strike + cache.getNameSp().setSpan(new StrikethroughSpan(), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } + + holder.text.setText(cache.getNameSp(), TextView.BufferType.SPANNABLE); + if (gcIconDrawables.containsKey(cache.getType())) { // cache icon + holder.text.setCompoundDrawablesWithIntrinsicBounds(gcIconDrawables.get(cache.getType()), null, null, null); + } else { // unknown cache type, "mystery" icon + holder.text.setCompoundDrawablesWithIntrinsicBounds(gcIconDrawables.get(CacheType.MYSTERY), null, null, null); + } + + if (holder.inventory.getChildCount() > 0) { + holder.inventory.removeAllViews(); + } + + ImageView tbIcon = null; + if (cache.getInventoryItems() > 0) { + tbIcon = (ImageView) inflater.inflate(R.layout.trackable_icon, null); + tbIcon.setImageResource(R.drawable.trackable_all); + + holder.inventory.addView(tbIcon); + holder.inventory.setVisibility(View.VISIBLE); + } else { + holder.inventory.setVisibility(View.GONE); + } + + boolean setDiDi = false; + if (cache.getCoords() != null) { + holder.direction.setVisibility(View.VISIBLE); + holder.direction.updateAzimuth(azimuth); + if (coords != null) { + holder.distance.update(coords); + holder.direction.updateCoords(coords); + } + setDiDi = true; + } else { + if (cache.getDistance() != null) { + holder.distance.setDistance(cache.getDistance()); + setDiDi = true; + } + if (cache.getDirection() != null) { + holder.direction.setVisibility(View.VISIBLE); + holder.direction.updateAzimuth(azimuth); + holder.direction.updateHeading(cache.getDirection()); + setDiDi = true; + } + } + + if (setDiDi) { + holder.directionLayout.setVisibility(View.VISIBLE); + holder.dirImgLayout.setVisibility(View.GONE); + } else { + holder.directionLayout.setVisibility(View.GONE); + holder.distance.clear(); + + final Bitmap dirImgPre = BitmapFactory.decodeFile(DirectionImage.getDirectionFile(cache.getGeocode(), false).getPath()); + final Bitmap dirImg; + if (dirImgPre != null) { // null happens for invalid caches (not yet released) + dirImg = dirImgPre.copy(Bitmap.Config.ARGB_8888, true); + dirImgPre.recycle(); + } + else { + dirImg = null; + } + + if (dirImg != null) { + if (!Settings.isLightSkin()) { + int length = dirImg.getWidth() * dirImg.getHeight(); + int[] pixels = new int[length]; + dirImg.getPixels(pixels, 0, dirImg.getWidth(), 0, 0, dirImg.getWidth(), dirImg.getHeight()); + for (int i = 0; i < length; i++) { + if (pixels[i] == 0xff000000) { // replace black with white + pixels[i] = 0xffffffff; + } + } + dirImg.setPixels(pixels, 0, dirImg.getWidth(), 0, 0, dirImg.getWidth(), dirImg.getHeight()); + } + + holder.dirImg.setImageBitmap(dirImg); + holder.dirImgLayout.setVisibility(View.VISIBLE); + } else { + holder.dirImg.setImageBitmap(null); + holder.dirImgLayout.setVisibility(View.GONE); + } + } + + holder.favourite.setText(Integer.toString(cache.getFavoritePoints())); + + int favoriteBack; + // set default background, neither vote nor rating may be available + if (Settings.isLightSkin()) { + favoriteBack = R.drawable.favourite_background_light; + } else { + favoriteBack = R.drawable.favourite_background_dark; + } + float myVote = cache.getMyVote(); + if (myVote > 0) { // use my own rating for display, if I have voted + if (myVote >= 4) { + favoriteBack = ratingBcgs[2]; + } else if (myVote >= 3) { + favoriteBack = ratingBcgs[1]; + } else if (myVote > 0) { + favoriteBack = ratingBcgs[0]; + } + } else { + float rating = cache.getRating(); + if (rating >= 3.5) { + favoriteBack = ratingBcgs[2]; + } else if (rating >= 2.1) { + favoriteBack = ratingBcgs[1]; + } else if (rating > 0.0) { + favoriteBack = ratingBcgs[0]; + } + } + holder.favourite.setBackgroundResource(favoriteBack); + + if (cacheListType == CacheListType.HISTORY && cache.getVisitedDate() > 0) { + StringBuilder cacheInfo = new StringBuilder(50); + cacheInfo.append(cgBase.formatTime(cache.getVisitedDate())); + cacheInfo.append("; "); + cacheInfo.append(cgBase.formatDate(cache.getVisitedDate())); + holder.info.setText(cacheInfo.toString()); + } else { + ArrayList infos = new ArrayList(); + if (StringUtils.isNotBlank(cache.getGeocode())) { + infos.add(cache.getGeocode()); + } + if (cache.hasDifficulty()) { + infos.add("D " + String.format("%.1f", cache.getDifficulty())); + } + if (cache.hasTerrain()) { + infos.add("T " + String.format("%.1f", cache.getTerrain())); + } + + // don't show "not chosen" for events and virtuals, that should be the normal case + if (cache.getSize() != CacheSize.UNKNOWN && cache.showSize()) { + infos.add(cache.getSize().getL10n()); + } else if (cache.isEventCache() && cache.getHiddenDate() != null) { + infos.add(cgBase.formatShortDate(cache.getHiddenDate().getTime())); + } + + if (cache.isPremiumMembersOnly()) { + infos.add(res.getString(R.string.cache_premium)); + } + if (cacheListType != CacheListType.OFFLINE && cacheListType != CacheListType.HISTORY && cache.getListId() > 0) { + infos.add(res.getString(R.string.cache_offline)); + } + holder.info.setText(StringUtils.join(infos, SEPARATOR)); + } + + return v; + } + + @Override + public void notifyDataSetChanged() { + super.notifyDataSetChanged(); + + checked = 0; + for (cgCache cache : list) { + if (cache.isStatusChecked()) { + checked++; + } + } + + distances.clear(); + compasses.clear(); + } + + private class checkBoxListener implements View.OnClickListener { + + private cgCache cache = null; + + public checkBoxListener(cgCache cacheIn) { + cache = cacheIn; + } + + public void onClick(View view) { + final boolean checkNow = ((CheckBox) view).isChecked(); + + if (checkNow) { + cache.setStatusChecked(true); + checked++; + } else { + cache.setStatusChecked(false); + checked--; + } + } + } + + private class touchListener implements View.OnLongClickListener, View.OnClickListener, View.OnTouchListener { + + private String geocode = null; + private String name = null; + private cgCache cache = null; + private boolean touch = true; + private GestureDetector gestureDetector = null; + + public touchListener(String geocodeIn, String nameIn, cgCache cacheIn) { + geocode = geocodeIn; + name = nameIn; + cache = cacheIn; + + final detectGesture dGesture = new detectGesture(holder, cache); + gestureDetector = new GestureDetector(dGesture); + } + + // tap on item + public void onClick(View view) { + if (!touch) { + touch = true; + return; + } + + if (getSelectMode() || getChecked() > 0) { + return; + } + + // load cache details + Intent cachesIntent = new Intent(getContext(), CacheDetailActivity.class); + cachesIntent.putExtra("geocode", geocode); + cachesIntent.putExtra("name", name); + getContext().startActivity(cachesIntent); + } + + // long tap on item + public boolean onLongClick(View view) { + if (!touch) { + touch = true; + return true; + } + + return view.showContextMenu(); + } + + // swipe on item + public boolean onTouch(View view, MotionEvent event) { + if (gestureDetector.onTouchEvent(event)) { + touch = false; + return true; + } + + return false; + } + } + + class detectGesture extends GestureDetector.SimpleOnGestureListener { + + private CacheView holder = null; + private cgCache cache = null; + + public detectGesture(CacheView holderIn, cgCache cacheIn) { + holder = holderIn; + cache = cacheIn; + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + try { + if (getSelectMode()) { + return false; + } + + if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) { + return false; + } + + if ((e2.getX() - e1.getX()) > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > Math.abs(velocityY)) { + // left to right swipe + if (cache.isStatusChecked()) { + return true; + } + + if (holder != null && holder.oneInfo != null) { + checkChecked(+1); + holder.checkbox.setChecked(true); + cache.setStatusChecked(true); + moveRight(holder, cache, false); + } + + return true; + } else if ((e1.getX() - e2.getX()) > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > Math.abs(velocityY)) { + // right to left swipe + if (!cache.isStatusChecked()) { + return true; + } + + if (holder != null && holder.oneInfo != null) { + if (getSelectMode()) { + setSelectMode(false, false); + } + + checkChecked(-1); + holder.checkbox.setChecked(false); + cache.setStatusChecked(false); + moveLeft(holder, cache, false); + } + + return true; + } + } catch (Exception e) { + Log.w(Settings.tag, "CacheListAdapter.detectGesture.onFling: " + e.toString()); + } + + return false; + } + } + + private void checkChecked(int cnt) { + // check how many caches are selected, if any block sorting of list + checked += cnt; + sort = !(checked > 0 || getSelectMode()); + + if (sort) { + forceSort(coords); + } + } + + private void moveRight(CacheView holder, cgCache cache, boolean force) { + if (cache == null) { + return; + } + + holder.checkbox.setChecked(cache.isStatusChecked()); + + // slide cache info + final Animation showCheckbox = new TranslateAnimation(0, (int) (SWIPE_DISTANCE * pixelDensity), 0, 0); + showCheckbox.setRepeatCount(0); + showCheckbox.setDuration(force ? 0 : 400); + showCheckbox.setFillEnabled(true); + showCheckbox.setFillAfter(true); + showCheckbox.setInterpolator(new AccelerateDecelerateInterpolator()); + + // dim cache info + final Animation dimInfo = new AlphaAnimation(1.0f, SWIPE_OPACITY); + dimInfo.setRepeatCount(0); + dimInfo.setDuration(force ? 0 : 400); + dimInfo.setFillEnabled(true); + dimInfo.setFillAfter(true); + dimInfo.setInterpolator(new AccelerateDecelerateInterpolator()); + + // animation set (container) + final AnimationSet selectAnimation = new AnimationSet(true); + selectAnimation.setFillEnabled(true); + selectAnimation.setFillAfter(true); + + selectAnimation.addAnimation(showCheckbox); + selectAnimation.addAnimation(dimInfo); + + holder.oneInfo.startAnimation(selectAnimation); + cache.setStatusCheckedView(true); + } + + private void moveLeft(CacheView holder, cgCache cache, boolean force) { + if (cache == null) { + return; + } + + holder.checkbox.setChecked(cache.isStatusChecked()); + + // slide cache info + final Animation hideCheckbox = new TranslateAnimation((int) (SWIPE_DISTANCE * pixelDensity), 0, 0, 0); + hideCheckbox.setRepeatCount(0); + hideCheckbox.setDuration(force ? 0 : 400); + hideCheckbox.setFillEnabled(true); + hideCheckbox.setFillAfter(true); + hideCheckbox.setInterpolator(new AccelerateDecelerateInterpolator()); + + // brighten cache info + final Animation brightenInfo = new AlphaAnimation(SWIPE_OPACITY, 1.0f); + brightenInfo.setRepeatCount(0); + brightenInfo.setDuration(force ? 0 : 400); + brightenInfo.setFillEnabled(true); + brightenInfo.setFillAfter(true); + brightenInfo.setInterpolator(new AccelerateDecelerateInterpolator()); + + // animation set (container) + final AnimationSet selectAnimation = new AnimationSet(true); + selectAnimation.setFillEnabled(true); + selectAnimation.setFillAfter(true); + + selectAnimation.addAnimation(hideCheckbox); + selectAnimation.addAnimation(brightenInfo); + + holder.oneInfo.startAnimation(selectAnimation); + cache.setStatusCheckedView(false); + } + + public List getFilteredList() { + return list; + } +} diff --git a/main/src/cgeo/geocaching/ui/CacheView.java b/main/src/cgeo/geocaching/ui/CacheView.java new file mode 100644 index 0000000..7fba55d --- /dev/null +++ b/main/src/cgeo/geocaching/ui/CacheView.java @@ -0,0 +1,24 @@ +package cgeo.geocaching.ui; + + +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +public class CacheView { + // layouts & views + public RelativeLayout oneInfo; + public RelativeLayout oneCheckbox; + public CheckBox checkbox; + public ImageView logStatusMark; + public TextView text; + public TextView favourite; + public TextView info; + public RelativeLayout inventory; + public RelativeLayout directionLayout; + public DistanceView distance; + public CompassMiniView direction; + public RelativeLayout dirImgLayout; + public ImageView dirImg; +} diff --git a/main/src/cgeo/geocaching/ui/CompassMiniView.java b/main/src/cgeo/geocaching/ui/CompassMiniView.java new file mode 100644 index 0000000..5f3b8c2 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/CompassMiniView.java @@ -0,0 +1,175 @@ +package cgeo.geocaching.ui; + +import cgeo.geocaching.R; +import cgeo.geocaching.R.drawable; +import cgeo.geocaching.R.styleable; +import cgeo.geocaching.geopoint.Geopoint; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PaintFlagsDrawFilter; +import android.util.AttributeSet; +import android.view.View; + +public class CompassMiniView extends View { + private int arrowSkin = R.drawable.compass_arrow_mini_white; + private Context context = null; + private Geopoint cacheCoords = null; + private Bitmap compassArrow = null; + private float azimuth = 0; + private float heading = 0; + private PaintFlagsDrawFilter setfil = null; + private PaintFlagsDrawFilter remfil = null; + + public CompassMiniView(Context contextIn) { + super(contextIn); + context = contextIn; + } + + public CompassMiniView(Context contextIn, AttributeSet attrs) { + super(contextIn, attrs); + context = contextIn; + + TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.cgCompassMini); + int usedSkin = attributes.getInt(R.styleable.cgCompassMini_skin, 0); + if (usedSkin == 1) { + arrowSkin = R.drawable.compass_arrow_mini_black; + } else { + arrowSkin = R.drawable.compass_arrow_mini_white; + } + } + + @Override + public void onAttachedToWindow() { + compassArrow = BitmapFactory.decodeResource(context.getResources(), arrowSkin); + + setfil = new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG); + remfil = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0); + } + + @Override + public void onDetachedFromWindow() { + if (compassArrow != null) { + compassArrow.recycle(); + compassArrow = null; + } + } + + public void setContent(final Geopoint cacheCoordsIn) { + cacheCoords = cacheCoordsIn; + } + + protected void updateAzimuth(float azimuthIn) { + azimuth = azimuthIn; + + updateDirection(); + } + + protected void updateHeading(float headingIn) { + heading = headingIn; + + updateDirection(); + } + + protected void updateCoords(final Geopoint coordsIn) { + if (coordsIn == null || cacheCoords == null) { + return; + } + + heading = coordsIn.bearingTo(cacheCoords); + + updateDirection(); + } + + protected void updateDirection() { + if (compassArrow == null || compassArrow.isRecycled()) { + return; + } + + // compass margins + int compassRoseWidth = compassArrow.getWidth(); + int compassRoseHeight = compassArrow.getWidth(); + int marginLeft = (getWidth() - compassRoseWidth) / 2; + int marginTop = (getHeight() - compassRoseHeight) / 2; + + invalidate(marginLeft, marginTop, (marginLeft + compassRoseWidth), (marginTop + compassRoseHeight)); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + float azimuthRelative = azimuth - heading; + if (azimuthRelative < 0) { + azimuthRelative += 360; + } else if (azimuthRelative >= 360) { + azimuthRelative -= 360; + } + + // compass margins + canvas.setDrawFilter(setfil); + + int marginLeft = 0; + int marginTop = 0; + + int compassArrowWidth = compassArrow.getWidth(); + int compassArrowHeight = compassArrow.getWidth(); + + int canvasCenterX = (compassArrowWidth / 2) + ((getWidth() - compassArrowWidth) / 2); + int canvasCenterY = (compassArrowHeight / 2) + ((getHeight() - compassArrowHeight) / 2); + + marginLeft = (getWidth() - compassArrowWidth) / 2; + marginTop = (getHeight() - compassArrowHeight) / 2; + + canvas.rotate(-azimuthRelative, canvasCenterX, canvasCenterY); + canvas.drawBitmap(compassArrow, marginLeft, marginTop, null); + canvas.rotate(azimuthRelative, canvasCenterX, canvasCenterY); + + canvas.setDrawFilter(remfil); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); + } + + private int measureWidth(int measureSpec) { + int result = 0; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.EXACTLY) { + result = specSize; + } else { + result = 21 + getPaddingLeft() + getPaddingRight(); + + if (specMode == MeasureSpec.AT_MOST) { + result = Math.min(result, specSize); + } + } + + return result; + } + + private int measureHeight(int measureSpec) { + int result = 0; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.EXACTLY) { + result = specSize; + } else { + result = 21 + getPaddingTop() + getPaddingBottom(); + + if (specMode == MeasureSpec.AT_MOST) { + result = Math.min(result, specSize); + } + } + + return result; + } +} \ No newline at end of file diff --git a/main/src/cgeo/geocaching/ui/CompassView.java b/main/src/cgeo/geocaching/ui/CompassView.java new file mode 100644 index 0000000..20495c0 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/CompassView.java @@ -0,0 +1,291 @@ +package cgeo.geocaching.ui; + +import cgeo.geocaching.R; +import cgeo.geocaching.Settings; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PaintFlagsDrawFilter; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; + +public class CompassView extends View { + + private changeThread watchdog = null; + private volatile boolean wantStop = false; + private Context context = null; + private Bitmap compassUnderlay = null; + private Bitmap compassRose = null; + private Bitmap compassArrow = null; + private Bitmap compassOverlay = null; + /** + * North direction currently SHOWN on compass (not measured) + */ + private double azimuthShown = 0.0; + /** + * cache direction currently SHOWN on compass (not measured) + */ + private double cacheHeadingShown = 0.0; + /** + * cache direction measured from device, or 0.0 + */ + private double cacheHeadingMeasured = 0.0; + /** + * North direction measured from device, or 0.0 + */ + private double northMeasured = 0.0; + private PaintFlagsDrawFilter setfil = null; + private PaintFlagsDrawFilter remfil = null; + private int compassUnderlayWidth = 0; + private int compassUnderlayHeight = 0; + private int compassRoseWidth = 0; + private int compassRoseHeight = 0; + private int compassArrowWidth = 0; + private int compassArrowHeight = 0; + private int compassOverlayWidth = 0; + private int compassOverlayHeight = 0; + private boolean initialDisplay; + private Handler changeHandler = new Handler() { + + @Override + public void handleMessage(Message message) { + try { + invalidate(); + } catch (Exception e) { + Log.e(Settings.tag, "CompassView.changeHandler: " + e.toString()); + } + } + }; + + public CompassView(Context contextIn) { + super(contextIn); + context = contextIn; + } + + public CompassView(Context contextIn, AttributeSet attrs) { + super(contextIn, attrs); + context = contextIn; + } + + @Override + public void onAttachedToWindow() { + compassUnderlay = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_underlay); + compassRose = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_rose); + compassArrow = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_arrow); + compassOverlay = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_overlay); + + compassUnderlayWidth = compassUnderlay.getWidth(); + compassUnderlayHeight = compassUnderlay.getWidth(); + compassRoseWidth = compassRose.getWidth(); + compassRoseHeight = compassRose.getWidth(); + compassArrowWidth = compassArrow.getWidth(); + compassArrowHeight = compassArrow.getWidth(); + compassOverlayWidth = compassOverlay.getWidth(); + compassOverlayHeight = compassOverlay.getWidth(); + + setfil = new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG); + remfil = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0); + + initialDisplay = true; + wantStop = false; + + watchdog = new changeThread(); + watchdog.start(); + } + + @Override + public void onDetachedFromWindow() { + wantStop = true; + + if (compassUnderlay != null) { + compassUnderlay.recycle(); + } + + if (compassRose != null) { + compassRose.recycle(); + } + + if (compassArrow != null) { + compassArrow.recycle(); + } + + if (compassOverlay != null) { + compassOverlay.recycle(); + } + } + + public synchronized void updateNorth(double northHeadingIn, double cacheHeadingIn) { + if (initialDisplay) { + // We will force the compass to move brutally if this is the first + // update since it is visible. + azimuthShown = northHeadingIn; + cacheHeadingShown = cacheHeadingIn; + + // it may take some time to get an initial direction measurement for the device + if (northHeadingIn != 0.0) { + initialDisplay = false; + } + } + northMeasured = northHeadingIn; + cacheHeadingMeasured = cacheHeadingIn; + } + + /** + * Compute the new value, moving by small increments. + * + * @param goal + * the goal to reach + * @param actual + * the actual value + * @return the new value + */ + static protected double smoothUpdate(double goal, double actual) { + double diff = goal - actual; + final boolean largeDiff = Math.abs(diff) > 5; + + double offset = 0.0; + + if (diff < 0.0) { + diff += 360.0; + } else if (diff >= 360.0) { + diff -= 360.0; + } + + // If the difference is smaller than 1 degree, do nothing as it + // causes the arrow to vibrate. + if (diff > 1.0 && diff <= 180.0) { + offset = largeDiff ? 2.0 : 1.0; + } else if (diff > 180.0 && diff < 359.0) { + offset = largeDiff ? -2.0 : -1.0; + } + + return actual + offset; + } + + private class changeThread extends Thread { + + @Override + public void run() { + while (!wantStop) { + try { + sleep(50); + } catch (Exception e) { + // nothing + } + + synchronized (CompassView.this) { + azimuthShown = smoothUpdate(northMeasured, azimuthShown); + cacheHeadingShown = smoothUpdate(cacheHeadingMeasured, cacheHeadingShown); + } + + changeHandler.sendMessage(new Message()); + } + } + } + + @Override + protected void onDraw(Canvas canvas) { + // use local synchronized variables to avoid them being changed from the device during drawing + double azimuthDrawn; + double headingDrawn; + + synchronized (this) { + azimuthDrawn = azimuthShown; + headingDrawn = cacheHeadingShown; + } + + double azimuthTemp = azimuthDrawn; + double azimuthRelative = azimuthTemp - headingDrawn; + if (azimuthRelative < 0) { + azimuthRelative += 360; + } else if (azimuthRelative >= 360) { + azimuthRelative -= 360; + } + + // compass margins + int canvasCenterX = (compassRoseWidth / 2) + ((getWidth() - compassRoseWidth) / 2); + int canvasCenterY = (compassRoseHeight / 2) + ((getHeight() - compassRoseHeight) / 2); + + int marginLeftTemp = 0; + int marginTopTemp = 0; + + super.onDraw(canvas); + + canvas.save(); + canvas.setDrawFilter(setfil); + + marginLeftTemp = (getWidth() - compassUnderlayWidth) / 2; + marginTopTemp = (getHeight() - compassUnderlayHeight) / 2; + + canvas.drawBitmap(compassUnderlay, marginLeftTemp, marginTopTemp, null); + + marginLeftTemp = (getWidth() - compassRoseWidth) / 2; + marginTopTemp = (getHeight() - compassRoseHeight) / 2; + + canvas.rotate((float) -azimuthTemp, canvasCenterX, canvasCenterY); + canvas.drawBitmap(compassRose, marginLeftTemp, marginTopTemp, null); + canvas.rotate((float) azimuthTemp, canvasCenterX, canvasCenterY); + + marginLeftTemp = (getWidth() - compassArrowWidth) / 2; + marginTopTemp = (getHeight() - compassArrowHeight) / 2; + + canvas.rotate((float) -azimuthRelative, canvasCenterX, canvasCenterY); + canvas.drawBitmap(compassArrow, marginLeftTemp, marginTopTemp, null); + canvas.rotate((float) azimuthRelative, canvasCenterX, canvasCenterY); + + marginLeftTemp = (getWidth() - compassOverlayWidth) / 2; + marginTopTemp = (getHeight() - compassOverlayHeight) / 2; + + canvas.drawBitmap(compassOverlay, marginLeftTemp, marginTopTemp, null); + + canvas.setDrawFilter(remfil); + canvas.restore(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); + } + + private int measureWidth(int measureSpec) { + int result = 0; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.EXACTLY) { + result = specSize; + } else { + result = compassArrow.getWidth() + getPaddingLeft() + getPaddingRight(); + + if (specMode == MeasureSpec.AT_MOST) { + result = Math.min(result, specSize); + } + } + + return result; + } + + private int measureHeight(int measureSpec) { + int result = 0; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.EXACTLY) { + result = specSize; + } else { + result = compassArrow.getHeight() + getPaddingTop() + getPaddingBottom(); + + if (specMode == MeasureSpec.AT_MOST) { + result = Math.min(result, specSize); + } + } + + return result; + } +} \ No newline at end of file diff --git a/main/src/cgeo/geocaching/ui/DirectionImage.java b/main/src/cgeo/geocaching/ui/DirectionImage.java new file mode 100644 index 0000000..17c253a --- /dev/null +++ b/main/src/cgeo/geocaching/ui/DirectionImage.java @@ -0,0 +1,30 @@ +package cgeo.geocaching.ui; + +import cgeo.geocaching.Parameters; +import cgeo.geocaching.cgBase; +import cgeo.geocaching.files.LocalStorage; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpResponse; + +import java.io.File; + +public class DirectionImage { + + public static void getDrawable(final String geocode, final String code) { + if (StringUtils.isBlank(geocode) || StringUtils.isBlank(code)) { + return; + } + + final HttpResponse httpResponse = + cgBase.request("http://www.geocaching.com/ImgGen/seek/CacheDir.ashx", new Parameters("k", code), false); + if (httpResponse != null) { + LocalStorage.saveEntityToFile(httpResponse.getEntity(), getDirectionFile(geocode, true)); + } + } + + public static File getDirectionFile(final String geocode, final boolean createDirs) { + return LocalStorage.getStorageFile(geocode, "direction.png", false, createDirs); + } + +} \ No newline at end of file diff --git a/main/src/cgeo/geocaching/ui/DistanceView.java b/main/src/cgeo/geocaching/ui/DistanceView.java new file mode 100644 index 0000000..49c90b7 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/DistanceView.java @@ -0,0 +1,43 @@ +package cgeo.geocaching.ui; + +import cgeo.geocaching.cgBase; +import cgeo.geocaching.geopoint.Geopoint; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.TextView; + +public class DistanceView extends TextView { + private Geopoint cacheCoords = null; + + public DistanceView(Context context) { + super(context); + } + + public DistanceView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public DistanceView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public void setContent(final Geopoint cacheCoordsIn) { + cacheCoords = cacheCoordsIn; + } + + public void update(final Geopoint coords) { + if (cacheCoords == null || coords == null) { + return; + } + setText(cgBase.getHumanDistance(coords.distanceTo(cacheCoords))); + } + + public void setDistance(Float distance) { + setText("~" + cgBase.getHumanDistance(distance)); + } + + public void clear() { + setText(null); + } +} \ No newline at end of file diff --git a/main/src/cgeo/geocaching/ui/GPXListAdapter.java b/main/src/cgeo/geocaching/ui/GPXListAdapter.java new file mode 100644 index 0000000..23f38b0 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/GPXListAdapter.java @@ -0,0 +1,81 @@ +package cgeo.geocaching.ui; + +import cgeo.geocaching.R; +import cgeo.geocaching.Settings; +import cgeo.geocaching.cgeogpxes; +import cgeo.geocaching.R.id; +import cgeo.geocaching.R.layout; +import cgeo.geocaching.files.GPXImporter; + +import android.app.Activity; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import java.io.File; +import java.util.List; + +public class GPXListAdapter extends ArrayAdapter { + private GPXView holder = null; + private cgeogpxes parent = null; + private LayoutInflater inflater = null; + + public GPXListAdapter(cgeogpxes parentIn, List listIn) { + super(parentIn, 0, listIn); + + parent = parentIn; + } + + @Override + public View getView(final int position, final View rowView, final ViewGroup parent) { + if (inflater == null) { + inflater = ((Activity) getContext()).getLayoutInflater(); + } + + if (position > getCount()) { + Log.w(Settings.tag, "cgGPXListAdapter.getView: Attempt to access missing item #" + position); + return null; + } + + File file = getItem(position); + + View v = rowView; + + if (v == null) { + v = inflater.inflate(R.layout.gpx_item, null); + + holder = new GPXView(); + holder.filepath = (TextView) v.findViewById(R.id.filepath); + holder.filename = (TextView) v.findViewById(R.id.filename); + + v.setTag(holder); + } else { + holder = (GPXView) v.getTag(); + } + + final touchListener touchLst = new touchListener(file); + v.setOnClickListener(touchLst); + + holder.filepath.setText(file.getParent()); + holder.filename.setText(file.getName()); + + return v; + } + + private class touchListener implements View.OnClickListener { + private File file = null; + + public touchListener(File fileIn) { + file = fileIn; + } + + // tap on item + @Override + public void onClick(View view) { + (new GPXImporter(parent, parent.getListId(), null)).importGPX(file); + } + } +} diff --git a/main/src/cgeo/geocaching/ui/GPXView.java b/main/src/cgeo/geocaching/ui/GPXView.java new file mode 100644 index 0000000..a93d0db --- /dev/null +++ b/main/src/cgeo/geocaching/ui/GPXView.java @@ -0,0 +1,9 @@ +package cgeo.geocaching.ui; + +import android.widget.TextView; + +public class GPXView { + // layouts & views + public TextView filepath; + public TextView filename; +} diff --git a/main/src/cgeo/geocaching/ui/MapfileListAdapter.java b/main/src/cgeo/geocaching/ui/MapfileListAdapter.java new file mode 100644 index 0000000..cc16733 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/MapfileListAdapter.java @@ -0,0 +1,95 @@ +package cgeo.geocaching.ui; + +import cgeo.geocaching.R; +import cgeo.geocaching.Settings; +import cgeo.geocaching.cgSelectMapfile; +import cgeo.geocaching.R.id; +import cgeo.geocaching.R.layout; + +import android.app.Activity; +import android.graphics.Typeface; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import java.io.File; +import java.util.List; + +public class MapfileListAdapter extends ArrayAdapter { + + private cgSelectMapfile parentView; + private LayoutInflater inflater; + private MapfileView holder; + + public MapfileListAdapter(cgSelectMapfile parentIn, List listIn) { + super(parentIn, 0, listIn); + + parentView = parentIn; + } + + @Override + public View getView(final int position, final View rowView, final ViewGroup parent) { + if (inflater == null) { + inflater = ((Activity) getContext()).getLayoutInflater(); + } + + if (position > getCount()) { + Log.w(Settings.tag, "cgGPXListAdapter.getView: Attempt to access missing item #" + position); + return null; + } + + File file = getItem(position); + + View v = rowView; + + if (v == null) { + v = inflater.inflate(R.layout.mapfile_item, null); + + holder = new MapfileView(); + holder.filepath = (TextView) v.findViewById(R.id.mapfilepath); + holder.filename = (TextView) v.findViewById(R.id.mapfilename); + + v.setTag(holder); + } else { + holder = (MapfileView) v.getTag(); + } + + File current = new File(parentView.getCurrentMapfile()); + + if (file.equals(current)) { + holder.filename.setTypeface(holder.filename.getTypeface(), Typeface.BOLD); + } else { + holder.filename.setTypeface(holder.filename.getTypeface(), Typeface.NORMAL); + } + + final touchListener touchLst = new touchListener(file); + v.setOnClickListener(touchLst); + + holder.filepath.setText(file.getParent()); + holder.filename.setText(file.getName()); + + return v; + } + + private class touchListener implements View.OnClickListener { + private File file = null; + + public touchListener(File fileIn) { + file = fileIn; + } + + // tap on item + public void onClick(View view) { + parentView.setMapfile(file.toString()); + parentView.close(); + } + } + + private static class MapfileView { + public TextView filepath; + public TextView filename; + } +} -- cgit v1.1