net.exclaimindustries.geohashdroid.wiki.WikiMessageEditor.java Source code

Java tutorial

Introduction

Here is the source code for net.exclaimindustries.geohashdroid.wiki.WikiMessageEditor.java

Source

/**
 * WikiMessageEditor.java
 * Copyright (C)2009 Thomas Hirsch
 * Geohashdroid Copyright (C)2009 Nicholas Killewald
 * 
 * This file is distributed under the terms of the BSD license.
 * The source package should have a LICENSE file at the toplevel.
 */
package net.exclaimindustries.geohashdroid.wiki;

import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.exclaimindustries.geohashdroid.GeohashDroid;
import net.exclaimindustries.geohashdroid.R;
import net.exclaimindustries.geohashdroid.UnitConverter;
import net.exclaimindustries.geohashdroid.util.GHDConstants;
import net.exclaimindustries.geohashdroid.util.Info;
import net.exclaimindustries.tools.DateTools;

import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;

/**
 * Displays an edit box and a send button, which shall upload the message
 * entered to the appropriate expedition page in the Geohashing wiki. 
 * 
 * @author Thomas Hirsch
 */
public class WikiMessageEditor extends WikiBaseActivity {

    private static final Pattern RE_EXPEDITION = Pattern
            .compile("^(.*)(==+ ?Expedition ?==+.*?)(==+ ?.*? ?==+.*?)$", Pattern.DOTALL);

    private HashMap<String, String> mFormfields;

    private DecimalFormat mDistFormat = new DecimalFormat("###.######");

    private static final String DEBUG_TAG = "MessageEditor";

    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        mInfo = (Info) getIntent().getParcelableExtra(GeohashDroid.INFO);

        setContentView(R.layout.wikieditor);

        Button submitButton = (Button) findViewById(R.id.wikieditbutton);

        submitButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // We don't want to let the Activity handle the dialog.  That WILL
                // cause it to show up properly and all, but after a configuration
                // change (i.e. orientation shift), it won't show or update any text
                // (as far as I know), as we can't reassign the handler properly.
                // So, we'll handle it ourselves.
                mProgress = ProgressDialog.show(WikiMessageEditor.this, "", "", true, true, WikiMessageEditor.this);
                mConnectionHandler = new MessageConnectionRunner(mProgressHandler, WikiMessageEditor.this);
                mWikiConnectionThread = new Thread(mConnectionHandler, "WikiConnectionThread");
                mWikiConnectionThread.start();
            }
        });

        // In the event the text changes, update the submit button accordingly.
        TextWatcher tw = new TextWatcher() {

            @Override
            public void afterTextChanged(Editable s) {
                resetSubmitButton();
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                // Blah!
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                // BLAH!
            }

        };

        EditText editText = (EditText) findViewById(R.id.wikiedittext);
        editText.addTextChangedListener(tw);

        // Now, let's see if we have anything retained...
        try {
            RetainedThings retain = (RetainedThings) getLastNonConfigurationInstance();
            if (retain != null) {
                // We have something retained!  Thus, we need to construct the
                // popup and update it with the right status, assuming the
                // thread's still going.
                if (retain.thread != null && retain.thread.isAlive()) {
                    mProgress = ProgressDialog.show(WikiMessageEditor.this, "", "", true, true,
                            WikiMessageEditor.this);
                    mConnectionHandler = retain.handler;
                    mConnectionHandler.resetHandler(mProgressHandler);
                    mWikiConnectionThread = retain.thread;
                }
            }
        } catch (Exception ex) {
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Check for username/password here.  That way, when we get back from
        // the settings screen, it'll update the message accordingly.
        SharedPreferences prefs = getSharedPreferences(GHDConstants.PREFS_BASE, 0);
        TextView warning = (TextView) findViewById(R.id.warningmessage);
        String wpName = prefs.getString(GHDConstants.PREF_WIKI_USER, "");
        if ((wpName == null) || (wpName.trim().length() == 0)) {
            warning.setVisibility(View.VISIBLE);
        } else {
            warning.setVisibility(View.GONE);
        }

        resetSubmitButton();
    }

    @Override
    public Object onRetainNonConfigurationInstance() {
        // If the configuration changes (i.e. orientation shift), we want to
        // keep track of the thread we used to have.  That'll be used to
        // populate the new popup next time around, if need be.
        if (mWikiConnectionThread != null && mWikiConnectionThread.isAlive()) {
            mDontStopTheThread = true;
            RetainedThings retain = new RetainedThings();
            retain.handler = mConnectionHandler;
            retain.thread = mWikiConnectionThread;
            return retain;
        } else {
            return null;
        }
    }

    private class MessageConnectionRunner extends WikiConnectionRunner {
        MessageConnectionRunner(Handler h, Context c) {
            super(h, c);
        }

        public void run() {
            SharedPreferences prefs = getSharedPreferences(GHDConstants.PREFS_BASE, 0);

            boolean phoneTime = prefs.getBoolean(GHDConstants.PREF_WIKI_PHONE_TIME, false);

            try {
                HttpClient httpclient = new DefaultHttpClient();

                String wpName = prefs.getString(GHDConstants.PREF_WIKI_USER, "");
                if (!wpName.trim().equals("")) {
                    addStatus(R.string.wiki_conn_login);
                    String wpPassword = prefs.getString(GHDConstants.PREF_WIKI_PASS, "");
                    WikiUtils.login(httpclient, wpName, wpPassword);
                    addStatusAndNewline(R.string.wiki_conn_success);
                } else {
                    addStatusAndNewline(R.string.wiki_conn_anon_warning);
                }

                String expedition = WikiUtils.getWikiPageName(mInfo);

                String locationTag = "";

                // Location! Is the checkbox ticked (and do we have a location
                // handy)?
                CheckBox includelocation = (CheckBox) findViewById(R.id.includelocation);
                if (includelocation.isChecked()) {
                    Location lastLoc = getLastLocation();
                    if (lastLoc != null) {
                        String pos = mLatLonFormat.format(lastLoc.getLatitude()) + ","
                                + mLatLonFormat.format(lastLoc.getLongitude());
                        locationTag = " [http://www.openstreetmap.org/?lat="
                                + mLatLonLinkFormat.format(lastLoc.getLatitude()) + "&lon="
                                + mLatLonLinkFormat.format(lastLoc.getLongitude()) + "&zoom=16&layers=B000FTF @"
                                + pos + "]";
                        addStatus(R.string.wiki_conn_current_location);
                        addStatus(" " + pos + "\n");
                    } else {
                        addStatusAndNewline(R.string.wiki_conn_current_location_unknown);
                    }
                }

                addStatus(R.string.wiki_conn_expedition_retrieving);
                addStatus(" " + expedition + "...");
                String page;

                mFormfields = new HashMap<String, String>();
                page = WikiUtils.getWikiPage(httpclient, expedition, mFormfields);
                if ((page == null) || (page.trim().length() == 0)) {
                    addStatusAndNewline(R.string.wiki_conn_expedition_nonexistant);

                    // ok, let's create some.
                    addStatus(R.string.wiki_conn_expedition_creating);
                    WikiUtils.putWikiPage(httpclient, expedition,
                            WikiUtils.getWikiExpeditionTemplate(mInfo, WikiMessageEditor.this), mFormfields);
                    addStatusAndNewline(R.string.wiki_conn_success);

                    addStatus(R.string.wiki_conn_expedition_reretrieving);

                    page = WikiUtils.getWikiPage(httpclient, expedition, mFormfields);
                    addStatusAndNewline(R.string.wiki_conn_success);
                } else {
                    addStatusAndNewline(R.string.wiki_conn_success);
                }

                EditText editText = (EditText) findViewById(R.id.wikiedittext);

                // Change the summary so it has our message.
                String summaryPrefix;

                // We shouldn't say this is live, per se, if this is a
                // retrohash.
                if (mInfo.isRetroHash())
                    summaryPrefix = getText(R.string.wiki_post_message_summary_retro).toString();
                else
                    summaryPrefix = getText(R.string.wiki_post_message_summary).toString();

                mFormfields.put("summary", summaryPrefix + " " + editText.getText().toString());

                String before = "";
                String after = "";

                Matcher expeditionq = RE_EXPEDITION.matcher(page);
                if (expeditionq.matches()) {
                    before = expeditionq.group(1) + expeditionq.group(2);
                    after = expeditionq.group(3);
                } else {
                    before = page;
                }

                String localtime = DateTools.getWikiDateString(Calendar.getInstance());

                String message = "\n*" + editText.getText().toString().trim() + "  -- ~~~" + locationTag + " "
                        + (phoneTime ? localtime : "~~~~~") + "\n";

                addStatus(R.string.wiki_conn_insert_message);
                WikiUtils.putWikiPage(httpclient, expedition, before + message + after, mFormfields);
                addStatusAndNewline(R.string.wiki_conn_done);

                finishDialog();

                dismiss();
            } catch (WikiException ex) {
                String error = (String) getText(ex.getErrorTextId());
                Log.d(DEBUG_TAG, "WIKI EXCEPTION: " + error);
                error(error);
            } catch (Exception ex) {
                Log.d(DEBUG_TAG, "EXCEPTION: " + ex.getMessage());
                if (ex.getMessage() != null)
                    error(ex.getMessage());
                else
                    error((String) getText(R.string.wiki_error_unknown));
                return;
            }

        }
    }

    /**
     * Since onRetainNonConfigurationInstance returns a plain ol' Object, this
     * just holds the pieces of data we're retaining.
     */
    private class RetainedThings {
        public Thread thread;
        public WikiConnectionRunner handler;
    }

    private void resetSubmitButton() {
        // Make sure the submit button is disabled if there's no text ready.
        // That's all.  We can send things anonymously.
        Button submitButton = (Button) findViewById(R.id.wikieditbutton);
        EditText message = (EditText) findViewById(R.id.wikiedittext);

        if (message == null || message.getText().toString().length() <= 0) {
            submitButton.setEnabled(false);
        } else {
            submitButton.setEnabled(true);
        }
    }

    protected void doDismiss() {
        super.doDismiss();

        reset();
    }

    protected void reset() {
        // Wipe out the text.
        ((EditText) findViewById(R.id.wikiedittext)).setText("");
        resetSubmitButton();
    }

    @Override
    protected void locationUpdated() {
        super.locationUpdated();
        // Coordinates!  Update 'em!
        updateCoords();
    }

    private void updateCoords() {
        // Unlike in the wiki picture activity, we only have to concern
        // ourselves with the user's current location.  No picture location, nor
        // any need to change a text string.  Yay!
        Location lastLoc = getLastLocation();
        TextView tv;

        if (lastLoc != null) {
            tv = (TextView) (findViewById(R.id.coordstring));
            tv.setText(UnitConverter.makeFullCoordinateString(this, lastLoc, false, UnitConverter.OUTPUT_SHORT));

            tv = (TextView) (findViewById(R.id.diststring));
            tv.setText(UnitConverter.makeDistanceString(this, mDistFormat, mInfo.getDistanceInMeters(lastLoc)));
        } else {
            tv = (TextView) (findViewById(R.id.coordstring));
            tv.setText(R.string.standby_title);

            tv = (TextView) (findViewById(R.id.diststring));
            tv.setText(R.string.standby_title);
        }
    }
}