diff options
Diffstat (limited to 'main')
| -rw-r--r-- | main/res/layout/logs_page.xml (renamed from main/res/layout/cachedetail_logs_page.xml) | 0 | ||||
| -rw-r--r-- | main/res/layout/trackable_logs_view.xml | 13 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/CacheDetailActivity.java | 197 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/TrackableActivity.java | 174 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/ui/AbstractUserClickListener.java | 9 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/ui/HtmlImageCounter.java | 19 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/ui/OwnerActionsClickListener.java | 5 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/ui/UserActionsClickListener.java | 6 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java | 101 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/ui/logs/LogViewHolder.java (renamed from main/src/cgeo/geocaching/LogViewHolder.java) | 3 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java | 175 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java | 70 |
12 files changed, 390 insertions, 382 deletions
diff --git a/main/res/layout/cachedetail_logs_page.xml b/main/res/layout/logs_page.xml index 9aafd83..9aafd83 100644 --- a/main/res/layout/cachedetail_logs_page.xml +++ b/main/res/layout/logs_page.xml diff --git a/main/res/layout/trackable_logs_view.xml b/main/res/layout/trackable_logs_view.xml deleted file mode 100644 index 0f89c31..0000000 --- a/main/res/layout/trackable_logs_view.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<ListView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:cacheColorHint="?background_color" - android:divider="?background_color" - android:fastScrollEnabled="true" - android:focusable="false" - android:footerDividersEnabled="false" - android:headerDividersEnabled="false" - android:listSelector="?background_color" > - -</ListView>
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index d140be1..f39f215 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -14,7 +14,6 @@ import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.enumerations.CacheAttribute; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; -import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.geopoint.GeopointFormatter; import cgeo.geocaching.geopoint.Units; @@ -27,12 +26,13 @@ import cgeo.geocaching.ui.CacheDetailsCreator; import cgeo.geocaching.ui.CoordinatesFormatSwitcher; import cgeo.geocaching.ui.DecryptTextClickListener; import cgeo.geocaching.ui.EditNoteDialog; +import cgeo.geocaching.ui.HtmlImageCounter; import cgeo.geocaching.ui.EditNoteDialog.EditNoteDialogListener; +import cgeo.geocaching.ui.logs.CacheLogsViewCreator; import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.ui.ImagesList; import cgeo.geocaching.ui.LoggingUI; import cgeo.geocaching.ui.OwnerActionsClickListener; -import cgeo.geocaching.ui.UserActionsClickListener; import cgeo.geocaching.ui.WeakReferenceHandler; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.ClipboardUtils; @@ -105,12 +105,9 @@ import android.widget.TextView.BufferType; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.EnumSet; import java.util.List; import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; import java.util.regex.Pattern; /** @@ -1684,7 +1681,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } } } - } protected class DescriptionViewCreator extends AbstractCachingPageViewCreator<ScrollView> { @@ -1860,21 +1856,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc editNoteDialogListener.onFinishEditNoteDialog(note); } - private static class HtmlImageCounter implements Html.ImageGetter { - - private int imageCount = 0; - - @Override - public Drawable getDrawable(String url) { - imageCount++; - return null; - } - - public int getImageCount() { - return imageCount; - } - } - /** * Loads the description in background. <br /> * <br /> @@ -2018,176 +1999,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } } - private class LogsViewCreator extends AbstractCachingPageViewCreator<ListView> { - private final boolean allLogs; - - LogsViewCreator(boolean allLogs) { - this.allLogs = allLogs; - } - - @Override - public ListView getDispatchedView() { - if (cache == null) { - // something is really wrong - return null; - } - - view = (ListView) getLayoutInflater().inflate(R.layout.cachedetail_logs_page, null); - - // log count - final Map<LogType, Integer> logCounts = cache.getLogCounts(); - if (logCounts != null) { - final List<Entry<LogType, Integer>> sortedLogCounts = new ArrayList<Entry<LogType, Integer>>(logCounts.size()); - for (final Entry<LogType, Integer> entry : logCounts.entrySet()) { - // it may happen that the label is unknown -> then avoid any output for this type - if (entry.getKey() != LogType.PUBLISH_LISTING && entry.getKey().getL10n() != null) { - sortedLogCounts.add(entry); - } - } - - if (!sortedLogCounts.isEmpty()) { - // sort the log counts by type id ascending. that way the FOUND, DNF log types are the first and most visible ones - Collections.sort(sortedLogCounts, new Comparator<Entry<LogType, Integer>>() { - - @Override - public int compare(Entry<LogType, Integer> logCountItem1, Entry<LogType, Integer> logCountItem2) { - return logCountItem1.getKey().compareTo(logCountItem2.getKey()); - } - }); - - final ArrayList<String> labels = new ArrayList<String>(sortedLogCounts.size()); - for (final Entry<LogType, Integer> pair : sortedLogCounts) { - labels.add(pair.getValue() + "× " + pair.getKey().getL10n()); - } - - final TextView countView = new TextView(CacheDetailActivity.this); - countView.setText(res.getString(R.string.cache_log_types) + ": " + StringUtils.join(labels, ", ")); - view.addHeaderView(countView, null, false); - } - } - - final List<LogEntry> logs = allLogs ? cache.getLogs() : cache.getFriendsLogs(); - view.setAdapter(new ArrayAdapter<LogEntry>(CacheDetailActivity.this, R.layout.logs_item, logs) { - final UserActionsClickListener userActionsClickListener = new UserActionsClickListener(cache); - final DecryptTextClickListener decryptTextClickListener = new DecryptTextClickListener(); - - @Override - public View getView(final int position, final View convertView, final ViewGroup parent) { - View rowView = convertView; - if (null == rowView) { - rowView = getLayoutInflater().inflate(R.layout.logs_item, null); - } - LogViewHolder holder = (LogViewHolder) rowView.getTag(); - if (null == holder) { - holder = new LogViewHolder(rowView); - } - holder.setPosition(position); - - final LogEntry log = getItem(position); - - if (log.date > 0) { - holder.date.setText(Formatter.formatShortDateVerbally(log.date)); - holder.date.setVisibility(View.VISIBLE); - } else { - holder.date.setVisibility(View.GONE); - } - - holder.type.setText(log.type.getL10n()); - holder.author.setText(StringEscapeUtils.unescapeHtml4(log.author)); - - // finds count - holder.countOrLocation.setVisibility(View.VISIBLE); - if (log.found == -1) { - holder.countOrLocation.setVisibility(View.GONE); - } else { - holder.countOrLocation.setText(res.getQuantityString(R.plurals.cache_counts, log.found, log.found)); - } - - // logtext, avoid parsing HTML if not necessary - String logText = log.log; - if (TextUtils.containsHtml(logText)) { - logText = log.getDisplayText(); - // Fast preview: parse only HTML without loading any images - final HtmlImageCounter imageCounter = new HtmlImageCounter(); - final UnknownTagsHandler unknownTagsHandler = new UnknownTagsHandler(); - holder.text.setText(Html.fromHtml(logText, imageCounter, unknownTagsHandler), TextView.BufferType.SPANNABLE); - if (imageCounter.getImageCount() > 0) { - // Complete view: parse again with loading images - if necessary ! If there are any images causing problems the user can see at least the preview - final LogImageLoader loader = new LogImageLoader(holder); - loader.execute(logText); - } - } - else { - holder.text.setText(logText, TextView.BufferType.SPANNABLE); - } - - // images - if (log.hasLogImages()) { - holder.images.setText(log.getImageTitles()); - holder.images.setVisibility(View.VISIBLE); - holder.images.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ImagesActivity.startActivityLogImages(CacheDetailActivity.this, cache.getGeocode(), new ArrayList<Image>(log.getLogImages())); - } - }); - } else { - holder.images.setVisibility(View.GONE); - } - - // colored marker - final int marker = log.type.markerId; - if (marker != 0) { - holder.marker.setVisibility(View.VISIBLE); - holder.marker.setImageResource(marker); - } - else { - holder.marker.setVisibility(View.GONE); - } - - if (null == convertView) { - // if convertView != null then this listeners are already set - holder.author.setOnClickListener(userActionsClickListener); - holder.text.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); - holder.text.setOnClickListener(decryptTextClickListener); - registerForContextMenu(holder.text); - } - - return rowView; - } - }); - - return view; - } - - /** Loads the Log Images outside the ui thread. */ - - private class LogImageLoader extends AsyncTask<String, Progress, Spanned> { - final private LogViewHolder holder; - final private int position; - - public LogImageLoader(LogViewHolder holder) { - this.holder = holder; - this.position = holder.getPosition(); - } - - @Override - protected Spanned doInBackground(String... logtext) { - return Html.fromHtml(logtext[0], new HtmlImage(cache.getGeocode(), false, cache.getListId(), false), null); //, TextView.BufferType.SPANNABLE) - } - - @Override - protected void onPostExecute(Spanned result) { - // Ensure that this holder and its view still references the right item before updating the text. - if (position == holder.getPosition()) { - holder.text.setText(result); - } - } - - } - - } - private class WaypointsViewCreator extends AbstractCachingPageViewCreator<ScrollView> { @Override @@ -2528,10 +2339,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc return new DescriptionViewCreator(); case LOGS: - return new LogsViewCreator(true); + return new CacheLogsViewCreator(this, cache, true); case LOGSFRIENDS: - return new LogsViewCreator(false); + return new CacheLogsViewCreator(this, cache, false); case WAYPOINTS: return new WaypointsViewCreator(); diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java index 8dc29ee..9963d45 100644 --- a/main/src/cgeo/geocaching/TrackableActivity.java +++ b/main/src/cgeo/geocaching/TrackableActivity.java @@ -10,14 +10,14 @@ import cgeo.geocaching.connector.trackable.TrackableConnector; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.geopoint.Units; import cgeo.geocaching.network.HtmlImage; -import cgeo.geocaching.network.Network; import cgeo.geocaching.ui.AbstractCachingPageViewCreator; import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod; import cgeo.geocaching.ui.CacheDetailsCreator; import cgeo.geocaching.ui.Formatter; +import cgeo.geocaching.ui.UserActionsClickListener; +import cgeo.geocaching.ui.logs.TrackableLogsViewCreator; import cgeo.geocaching.utils.HtmlUtils; import cgeo.geocaching.utils.Log; -import cgeo.geocaching.utils.TextUtils; import cgeo.geocaching.utils.UnknownTagsHandler; import org.apache.commons.lang3.StringUtils; @@ -32,16 +32,12 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.text.Html; -import android.view.ContextMenu; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.ListView; -import android.widget.RelativeLayout; import android.widget.ScrollView; import android.widget.TextView; @@ -61,12 +57,12 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi this.resId = resId; } } + private Trackable trackable = null; private String geocode = null; private String name = null; private String guid = null; private String id = null; - private String contextMenuUser = null; private LayoutInflater inflater = null; private ProgressDialog waitDialog = null; private final Handler loadTrackableHandler = new Handler() { @@ -192,55 +188,6 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi } @Override - public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) { - - // FIXME: replace this context menu stuff by a UserActionsClickListener instead. - - super.onCreateContextMenu(menu, view, info); - final int viewId = view.getId(); - - if (viewId == R.id.author) { // Log item author - contextMenuUser = ((TextView) view).getText().toString(); - } else { // Trackable owner, and user holding trackable now - final RelativeLayout itemLayout = (RelativeLayout) view.getParent(); - final TextView itemName = (TextView) itemLayout.findViewById(R.id.name); - - final String selectedName = itemName.getText().toString(); - if (selectedName.equals(res.getString(R.string.trackable_owner))) { - contextMenuUser = trackable.getOwner(); - } else if (selectedName.equals(res.getString(R.string.trackable_spotted))) { - contextMenuUser = trackable.getSpottedName(); - } - } - - menu.setHeaderTitle(res.getString(R.string.user_menu_title) + " " + contextMenuUser); - menu.add(viewId, 1, 0, res.getString(R.string.user_menu_view_hidden)); - menu.add(viewId, 2, 0, res.getString(R.string.user_menu_view_found)); - menu.add(viewId, 3, 0, res.getString(R.string.user_menu_open_browser)); - menu.add(viewId, 4, 0, res.getString(R.string.user_menu_send_message)); - } - - @Override - public boolean onContextItemSelected(final MenuItem item) { - switch (item.getItemId()) { - case 1: - cgeocaches.startActivityOwner(this, contextMenuUser); - return true; - case 2: - cgeocaches.startActivityUserName(this, contextMenuUser); - return true; - case 3: - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + Network.encode(contextMenuUser)))); - return true; - case 4: - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/email/?u=" + Network.encode(contextMenuUser)))); - return true; - default: - return false; - } - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.trackable_activity, menu); return true; @@ -301,23 +248,6 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi } } - private class UserActionsListener implements View.OnClickListener { - - @Override - public void onClick(View view) { - if (view == null) { - return; - } - - try { - registerForContextMenu(view); - openContextMenu(view); - } catch (final Exception e) { - Log.e("TrackableActivity.UserActionsListener.onClick ", e); - } - } - } - private class TrackableIconThread extends Thread { final private String url; final private Handler handler; @@ -377,7 +307,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi case DETAILS: return new DetailsViewCreator(); case LOGS: - return new LogsViewCreator(); + return new TrackableLogsViewCreator(this, trackable); default: throw new IllegalArgumentException(); } @@ -398,98 +328,6 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi return new ImmutablePair<List<? extends Page>, Integer>(pages, 0); } - public class LogsViewCreator extends AbstractCachingPageViewCreator<ListView> { - - @Override - public ListView getDispatchedView() { - view = (ListView) getLayoutInflater().inflate(R.layout.trackable_logs_view, null); - - if (trackable != null && trackable.getLogs() != null) { - view.setAdapter(new ArrayAdapter<LogEntry>(TrackableActivity.this, R.layout.logs_item, trackable.getLogs()) { - @Override - public View getView(int position, View convertView, android.view.ViewGroup parent) { - View rowView = convertView; - if (null == rowView) { - rowView = getLayoutInflater().inflate(R.layout.logs_item, null); - } - LogViewHolder holder = (LogViewHolder) rowView.getTag(); - if (null == holder) { - holder = new LogViewHolder(rowView); - } - - final LogEntry log = getItem(position); - fillViewHolder(holder, log); - return rowView; - } - }); - } - return view; - } - - protected void fillViewHolder(LogViewHolder holder, final LogEntry log) { - if (log.date > 0) { - holder.date.setText(Formatter.formatShortDateVerbally(log.date)); - } - - holder.type.setText(log.type.getL10n()); - holder.author.setText(Html.fromHtml(log.author), TextView.BufferType.SPANNABLE); - - if (StringUtils.isBlank(log.cacheName)) { - holder.countOrLocation.setVisibility(View.GONE); - } else { - holder.countOrLocation.setText(Html.fromHtml(log.cacheName)); - final String cacheGuid = log.cacheGuid; - final String cacheName = log.cacheName; - holder.countOrLocation.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View arg0) { - CacheDetailActivity.startActivityGuid(TrackableActivity.this, cacheGuid, Html.fromHtml(cacheName).toString()); - } - }); - } - - final TextView logView = holder.text; - logView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); - - String logText = log.log; - if (TextUtils.containsHtml(logText)) { - logText = log.getDisplayText(); - logView.setText(Html.fromHtml(logText, new HtmlImage(null, false, StoredList.TEMPORARY_LIST_ID, false), null), TextView.BufferType.SPANNABLE); - } - else { - logView.setText(logText); - } - - final ImageView statusMarker = holder.marker; - // colored marker - final int marker = log.type.markerId; - if (marker != 0) { - statusMarker.setVisibility(View.VISIBLE); - statusMarker.setImageResource(marker); - } - else { - statusMarker.setVisibility(View.GONE); - } - - // images - if (log.hasLogImages()) { - holder.images.setText(log.getImageTitles()); - holder.images.setVisibility(View.VISIBLE); - holder.images.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ImagesActivity.startActivityLogImages(TrackableActivity.this, trackable.getGeocode(), new ArrayList<Image>(log.getLogImages())); - } - }); - } else { - holder.images.setVisibility(View.GONE); - } - - holder.author.setOnClickListener(new UserActionsListener()); - } - - } - public class DetailsViewCreator extends AbstractCachingPageViewCreator<ScrollView> { @InjectView(R.id.goal_box) protected LinearLayout goalBox; @@ -533,7 +371,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi final TextView owner = details.add(R.string.trackable_owner, res.getString(R.string.trackable_unknown)); if (StringUtils.isNotBlank(trackable.getOwner())) { owner.setText(Html.fromHtml(trackable.getOwner()), TextView.BufferType.SPANNABLE); - owner.setOnClickListener(new UserActionsListener()); + owner.setOnClickListener(new UserActionsClickListener()); } // trackable spotted @@ -577,7 +415,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi } }); } else if (Trackable.SPOTTED_USER == trackable.getSpottedType()) { - spotted.setOnClickListener(new UserActionsListener()); + spotted.setOnClickListener(new UserActionsClickListener()); } } diff --git a/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java b/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java index b5e5c9a..b717568 100644 --- a/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java +++ b/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java @@ -1,6 +1,5 @@ package cgeo.geocaching.ui; -import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.cgeocaches; import cgeo.geocaching.activity.AbstractActivity; @@ -15,10 +14,10 @@ import android.view.View; abstract class AbstractUserClickListener implements View.OnClickListener { - protected final Geocache cache; + private final boolean enabled; - public AbstractUserClickListener(final Geocache cache) { - this.cache = cache; + public AbstractUserClickListener(final boolean enabled) { + this.enabled = enabled; } @Override @@ -26,7 +25,7 @@ abstract class AbstractUserClickListener implements View.OnClickListener { if (view == null) { return; } - if (!cache.supportsUserActions()) { + if (!enabled) { return; } diff --git a/main/src/cgeo/geocaching/ui/HtmlImageCounter.java b/main/src/cgeo/geocaching/ui/HtmlImageCounter.java new file mode 100644 index 0000000..24b70ea --- /dev/null +++ b/main/src/cgeo/geocaching/ui/HtmlImageCounter.java @@ -0,0 +1,19 @@ +package cgeo.geocaching.ui; + +import android.graphics.drawable.Drawable; +import android.text.Html; + +public class HtmlImageCounter implements Html.ImageGetter { + + private int imageCount = 0; + + @Override + public Drawable getDrawable(String url) { + imageCount++; + return null; + } + + public int getImageCount() { + return imageCount; + } +}
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/ui/OwnerActionsClickListener.java b/main/src/cgeo/geocaching/ui/OwnerActionsClickListener.java index e7b04a5..45ce237 100644 --- a/main/src/cgeo/geocaching/ui/OwnerActionsClickListener.java +++ b/main/src/cgeo/geocaching/ui/OwnerActionsClickListener.java @@ -12,8 +12,11 @@ import android.widget.TextView; */ public class OwnerActionsClickListener extends AbstractUserClickListener { + private final Geocache cache; + public OwnerActionsClickListener(Geocache cache) { - super(cache); + super(cache.supportsUserActions()); + this.cache = cache; } @Override diff --git a/main/src/cgeo/geocaching/ui/UserActionsClickListener.java b/main/src/cgeo/geocaching/ui/UserActionsClickListener.java index 8235446..292074e 100644 --- a/main/src/cgeo/geocaching/ui/UserActionsClickListener.java +++ b/main/src/cgeo/geocaching/ui/UserActionsClickListener.java @@ -11,7 +11,11 @@ import android.widget.TextView; public class UserActionsClickListener extends AbstractUserClickListener { public UserActionsClickListener(Geocache cache) { - super(cache); + super(cache.supportsUserActions()); + } + + public UserActionsClickListener() { + super(true); } @Override diff --git a/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java new file mode 100644 index 0000000..a785681 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java @@ -0,0 +1,101 @@ +package cgeo.geocaching.ui.logs; + +import cgeo.geocaching.CacheDetailActivity; +import cgeo.geocaching.Geocache; +import cgeo.geocaching.LogEntry; +import cgeo.geocaching.R; +import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.enumerations.LogType; +import cgeo.geocaching.ui.UserActionsClickListener; + +import org.apache.commons.lang3.StringUtils; + +import android.content.res.Resources; +import android.view.View; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +public class CacheLogsViewCreator extends LogsViewCreator { + private final boolean allLogs; + private final Geocache cache; + private final Resources res = cgeoapplication.getInstance().getResources(); + + public CacheLogsViewCreator(CacheDetailActivity cacheDetailActivity, final Geocache cache, boolean allLogs) { + super(cacheDetailActivity); + this.cache = cache; + this.allLogs = allLogs; + } + + @Override + protected List<LogEntry> getLogs() { + return allLogs ? cache.getLogs() : cache.getFriendsLogs(); + } + + @Override + protected void addHeaderView() { + // adds the log counts + final Map<LogType, Integer> logCounts = cache.getLogCounts(); + if (logCounts != null) { + final List<Entry<LogType, Integer>> sortedLogCounts = new ArrayList<Entry<LogType, Integer>>(logCounts.size()); + for (final Entry<LogType, Integer> entry : logCounts.entrySet()) { + // it may happen that the label is unknown -> then avoid any output for this type + if (entry.getKey() != LogType.PUBLISH_LISTING && entry.getKey().getL10n() != null) { + sortedLogCounts.add(entry); + } + } + + if (!sortedLogCounts.isEmpty()) { + // sort the log counts by type id ascending. that way the FOUND, DNF log types are the first and most visible ones + Collections.sort(sortedLogCounts, new Comparator<Entry<LogType, Integer>>() { + + @Override + public int compare(Entry<LogType, Integer> logCountItem1, Entry<LogType, Integer> logCountItem2) { + return logCountItem1.getKey().compareTo(logCountItem2.getKey()); + } + }); + + final ArrayList<String> labels = new ArrayList<String>(sortedLogCounts.size()); + for (final Entry<LogType, Integer> pair : sortedLogCounts) { + labels.add(pair.getValue() + "× " + pair.getKey().getL10n()); + } + + final TextView countView = new TextView(activity); + countView.setText(res.getString(R.string.cache_log_types) + ": " + StringUtils.join(labels, ", ")); + view.addHeaderView(countView, null, false); + } + } + } + + @Override + protected void fillCountOrLocation(LogViewHolder holder, final LogEntry log) { + // finds count + if (log.found == -1) { + holder.countOrLocation.setVisibility(View.GONE); + } else { + holder.countOrLocation.setVisibility(View.VISIBLE); + holder.countOrLocation.setText(res.getQuantityString(R.plurals.cache_counts, log.found, log.found)); + } + } + + @Override + protected boolean isValid() { + return cache != null; + } + + @Override + protected String getGeocode() { + return cache.getGeocode(); + } + + @Override + protected UserActionsClickListener createUserActionsListener() { + return new UserActionsClickListener(cache); + } + +}
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/LogViewHolder.java b/main/src/cgeo/geocaching/ui/logs/LogViewHolder.java index 14148d0..16f5537 100644 --- a/main/src/cgeo/geocaching/LogViewHolder.java +++ b/main/src/cgeo/geocaching/ui/logs/LogViewHolder.java @@ -1,7 +1,8 @@ -package cgeo.geocaching; +package cgeo.geocaching.ui.logs; import butterknife.InjectView; +import cgeo.geocaching.R; import cgeo.geocaching.ui.AbstractViewHolder; import android.view.View; diff --git a/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java new file mode 100644 index 0000000..ee2713a --- /dev/null +++ b/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java @@ -0,0 +1,175 @@ +package cgeo.geocaching.ui.logs; + +import cgeo.geocaching.Image; +import cgeo.geocaching.ImagesActivity; +import cgeo.geocaching.LogEntry; +import cgeo.geocaching.R; +import cgeo.geocaching.StoredList; +import cgeo.geocaching.activity.AbstractActivity; +import cgeo.geocaching.activity.Progress; +import cgeo.geocaching.network.HtmlImage; +import cgeo.geocaching.ui.AbstractCachingPageViewCreator; +import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod; +import cgeo.geocaching.ui.DecryptTextClickListener; +import cgeo.geocaching.ui.Formatter; +import cgeo.geocaching.ui.HtmlImageCounter; +import cgeo.geocaching.ui.UserActionsClickListener; +import cgeo.geocaching.utils.TextUtils; +import cgeo.geocaching.utils.UnknownTagsHandler; + +import org.apache.commons.lang3.StringEscapeUtils; + +import android.os.AsyncTask; +import android.text.Html; +import android.text.Spanned; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + +public abstract class LogsViewCreator extends AbstractCachingPageViewCreator<ListView> { + + protected final AbstractActivity activity; + + public LogsViewCreator(AbstractActivity activity) { + this.activity = activity; + } + + @Override + public ListView getDispatchedView() { + if (!isValid()) { + return null; + } + + final List<LogEntry> logs = getLogs(); + + view = (ListView) activity.getLayoutInflater().inflate(R.layout.logs_page, null); + addHeaderView(); + view.setAdapter(new ArrayAdapter<LogEntry>(activity, R.layout.logs_item, logs) { + + @Override + public View getView(final int position, final View convertView, final android.view.ViewGroup parent) { + View rowView = convertView; + if (null == rowView) { + rowView = activity.getLayoutInflater().inflate(R.layout.logs_item, null); + } + LogViewHolder holder = (LogViewHolder) rowView.getTag(); + if (null == holder) { + holder = new LogViewHolder(rowView); + } + holder.setPosition(position); + + final LogEntry log = getItem(position); + fillViewHolder(convertView, holder, log); + return rowView; + } + }); + + return view; + } + + protected void fillViewHolder(final View convertView, LogViewHolder holder, final LogEntry log) { + if (log.date > 0) { + holder.date.setText(Formatter.formatShortDateVerbally(log.date)); + holder.date.setVisibility(View.VISIBLE); + } else { + holder.date.setVisibility(View.GONE); + } + + holder.type.setText(log.type.getL10n()); + holder.author.setText(StringEscapeUtils.unescapeHtml4(log.author)); + + fillCountOrLocation(holder, log); + + // logtext, avoid parsing HTML if not necessary + String logText = log.log; + if (TextUtils.containsHtml(logText)) { + logText = log.getDisplayText(); + // Fast preview: parse only HTML without loading any images + final HtmlImageCounter imageCounter = new HtmlImageCounter(); + final UnknownTagsHandler unknownTagsHandler = new UnknownTagsHandler(); + holder.text.setText(Html.fromHtml(logText, imageCounter, unknownTagsHandler), TextView.BufferType.SPANNABLE); + if (imageCounter.getImageCount() > 0) { + // Complete view: parse again with loading images - if necessary ! If there are any images causing problems the user can see at least the preview + final LogImageLoader loader = new LogImageLoader(holder); + loader.execute(logText); + } + } + else { + holder.text.setText(logText, TextView.BufferType.SPANNABLE); + } + + // images + if (log.hasLogImages()) { + holder.images.setText(log.getImageTitles()); + holder.images.setVisibility(View.VISIBLE); + holder.images.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ImagesActivity.startActivityLogImages(activity, getGeocode(), new ArrayList<Image>(log.getLogImages())); + } + }); + } else { + holder.images.setVisibility(View.GONE); + } + + // colored marker + final int marker = log.type.markerId; + if (marker != 0) { + holder.marker.setVisibility(View.VISIBLE); + holder.marker.setImageResource(marker); + } + else { + holder.marker.setVisibility(View.GONE); + } + + if (null == convertView) { + holder.author.setOnClickListener(createUserActionsListener()); + holder.text.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); + holder.text.setOnClickListener(new DecryptTextClickListener()); + activity.registerForContextMenu(holder.text); + } + } + + abstract protected UserActionsClickListener createUserActionsListener(); + + abstract protected String getGeocode(); + + abstract protected List<LogEntry> getLogs(); + + abstract protected void addHeaderView(); + + abstract protected void fillCountOrLocation(LogViewHolder holder, final LogEntry log); + + abstract protected boolean isValid(); + + /** Loads the Log Images outside the ui thread. */ + + private class LogImageLoader extends AsyncTask<String, Progress, Spanned> { + final private LogViewHolder holder; + final private int position; + + public LogImageLoader(LogViewHolder holder) { + this.holder = holder; + this.position = holder.getPosition(); + } + + @Override + protected Spanned doInBackground(String... logtext) { + return Html.fromHtml(logtext[0], new HtmlImage(getGeocode(), false, StoredList.STANDARD_LIST_ID, false), null); //, TextView.BufferType.SPANNABLE) + } + + @Override + protected void onPostExecute(Spanned result) { + // Ensure that this holder and its view still references the right item before updating the text. + if (position == holder.getPosition()) { + holder.text.setText(result); + } + } + + } + +} diff --git a/main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java new file mode 100644 index 0000000..4c57406 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java @@ -0,0 +1,70 @@ +package cgeo.geocaching.ui.logs; + +import cgeo.geocaching.CacheDetailActivity; +import cgeo.geocaching.LogEntry; +import cgeo.geocaching.Trackable; +import cgeo.geocaching.TrackableActivity; +import cgeo.geocaching.ui.UserActionsClickListener; + +import org.apache.commons.lang3.StringUtils; + +import android.text.Html; +import android.view.View; + +import java.util.List; + +public class TrackableLogsViewCreator extends LogsViewCreator { + + private final Trackable trackable; + + /** + * @param trackableActivity + */ + public TrackableLogsViewCreator(TrackableActivity trackableActivity, final Trackable trackable) { + super(trackableActivity); + this.trackable = trackable; + } + + @Override + protected boolean isValid() { + return trackable != null; + } + + @Override + protected List<LogEntry> getLogs() { + return trackable.getLogs(); + } + + @Override + protected void addHeaderView() { + // empty + } + + @Override + protected void fillCountOrLocation(LogViewHolder holder, final LogEntry log) { + if (StringUtils.isBlank(log.cacheName)) { + holder.countOrLocation.setVisibility(View.GONE); + } else { + holder.countOrLocation.setText(Html.fromHtml(log.cacheName)); + final String cacheGuid = log.cacheGuid; + final String cacheName = log.cacheName; + holder.countOrLocation.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View arg0) { + CacheDetailActivity.startActivityGuid(activity, cacheGuid, Html.fromHtml(cacheName).toString()); + } + }); + } + } + + @Override + protected String getGeocode() { + return trackable.getGeocode(); + } + + @Override + protected UserActionsClickListener createUserActionsListener() { + return new UserActionsClickListener(); + } + +}
\ No newline at end of file |
