aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/ui/logs
diff options
context:
space:
mode:
authorBananeweizen <bananeweizen@gmx.de>2013-06-22 20:51:14 +0200
committerBananeweizen <bananeweizen@gmx.de>2013-06-23 09:08:21 +0200
commit9e9e7c2f8ce38be8b1a02a8b8632f919fa81d203 (patch)
tree9739a96c9891a62745f7cee0dff5ed63ccf739dd /main/src/cgeo/geocaching/ui/logs
parentec9af65d1d5130b0c046c58b964dfd04944eb218 (diff)
downloadcgeo-9e9e7c2f8ce38be8b1a02a8b8632f919fa81d203.zip
cgeo-9e9e7c2f8ce38be8b1a02a8b8632f919fa81d203.tar.gz
cgeo-9e9e7c2f8ce38be8b1a02a8b8632f919fa81d203.tar.bz2
#2910: remove code duplication in logs views
Diffstat (limited to 'main/src/cgeo/geocaching/ui/logs')
-rw-r--r--main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java101
-rw-r--r--main/src/cgeo/geocaching/ui/logs/LogViewHolder.java47
-rw-r--r--main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java175
-rw-r--r--main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java70
4 files changed, 393 insertions, 0 deletions
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/ui/logs/LogViewHolder.java b/main/src/cgeo/geocaching/ui/logs/LogViewHolder.java
new file mode 100644
index 0000000..16f5537
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/logs/LogViewHolder.java
@@ -0,0 +1,47 @@
+package cgeo.geocaching.ui.logs;
+
+import butterknife.InjectView;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.ui.AbstractViewHolder;
+
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+public class LogViewHolder extends AbstractViewHolder {
+ @InjectView(R.id.added) protected TextView date ;
+ @InjectView(R.id.type) protected TextView type;
+ @InjectView(R.id.author) protected TextView author;
+ @InjectView(R.id.count_or_location) protected TextView countOrLocation;
+ @InjectView(R.id.log) protected TextView text;
+ @InjectView(R.id.log_images) protected TextView images;
+ @InjectView(R.id.log_mark) protected ImageView marker;
+
+ private int position;
+
+ public LogViewHolder(View rowView) {
+ super(rowView);
+ }
+
+ /**
+ * Read the position of the cursor pointed to by this holder. <br/>
+ * This must be called by the UI thread.
+ *
+ * @return the cursor position
+ */
+ public int getPosition() {
+ return position;
+ }
+
+ /**
+ * Set the position of the cursor pointed to by this holder. <br/>
+ * This must be called by the UI thread.
+ *
+ * @param position
+ * the cursor position
+ */
+ public void setPosition(final int position) {
+ this.position = position;
+ }
+} \ No newline at end of file
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