se.toxbee.sleepfighter.activity.EditGPSFilterAreaActivity.java Source code

Java tutorial

Introduction

Here is the source code for se.toxbee.sleepfighter.activity.EditGPSFilterAreaActivity.java

Source

/*******************************************************************************
 * Copyright (c) 2013 See AUTHORS file.
 * 
 * This file is part of SleepFighter.
 * 
 * SleepFighter is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * SleepFighter is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with SleepFighter. If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package se.toxbee.sleepfighter.activity;

import java.util.List;

import net.engio.mbassy.listener.Handler;
import se.toxbee.sleepfighter.R;
import se.toxbee.sleepfighter.SFApplication;
import se.toxbee.sleepfighter.android.location.LocationAdapter;
import se.toxbee.sleepfighter.gps.GPSFilterLocationRetriever;
import se.toxbee.sleepfighter.model.gps.GPSFilterArea;
import se.toxbee.sleepfighter.model.gps.GPSFilterAreaSet;
import se.toxbee.sleepfighter.model.gps.GPSFilterMode;
import se.toxbee.sleepfighter.model.gps.GPSFilterPolygon;
import se.toxbee.sleepfighter.model.gps.GPSLatLng;
import se.toxbee.sleepfighter.text.GPSFilterTextUtils;
import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Point;
import android.location.Criteria;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.text.Html;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnCameraChangeListener;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
import com.google.android.gms.maps.GoogleMap.OnMarkerDragListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polygon;
import com.google.android.gms.maps.model.PolygonOptions;
import com.google.common.collect.Lists;

/**
 * EditGPSFilterAreaActivity is the activity for editing an GPSFilterArea.
 *
 * @author Centril<twingoow@gmail.com> / Mazdak Farrokhzad.
 * @version 1.0
 * @since Oct 6, 2013
 */
public class EditGPSFilterAreaActivity extends FragmentActivity
        implements OnMapClickListener, OnMarkerDragListener, OnMarkerClickListener {
    private static final String TAG = EditGPSFilterAreaActivity.class.getSimpleName();

    public static final String EXTRAS_AREA_ID = "gpsfilter_area_id";
    public static final String EXTRAS_AREA_IS_NEW = "gpsfilter_are_isnew";

    private static final int POLYGON_EXCLUDE_FILL_COLOR = R.color.gpsfilter_polygon_fill_exclude;
    private static final int POLYGON_INCLUDE_FILL_COLOR = R.color.gpsfilter_polygon_fill_include;
    private static final int POLYGON_STROKE_COLOR = R.color.shadow;
    private static final boolean POLYGON_GEODESIC = true; // The earth is a sphere, so bend polygon?

    private static final float MAP_MY_LOCATION_ZOOM = 13f;
    private static final float CAMERA_MOVE_BOUNDS_PADDING = 0.2f; // padding as a % of lowest of screen width/height.

    private static final long MAX_LOCATION_FIX_AGE = 5 * 60 * 1000; // 5 minutes.

    private static final long SPLASH_FADE_DELAY = 150;

    private GoogleMap googleMap;

    private List<Marker> markers;

    private Polygon poly;

    private LinearLayout splashInfoContainer;

    private Animation splashFadeOut;

    private GPSFilterArea area;

    private GPSFilterAreaSet set;

    private boolean isNew;

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private void setupActionBar() {
        String name = this.printName();

        if (Build.VERSION.SDK_INT >= 11) {
            // add the custom view to the action bar.
            ActionBar actionBar = getActionBar();
            actionBar.setCustomView(R.layout.gpsfilter_area_actionbar);
            actionBar.setDisplayOptions(
                    ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_CUSTOM);

            View customView = actionBar.getCustomView();

            // Setup edit name component.
            EditText editNameView = (EditText) customView.findViewById(R.id.edit_gpsfilter_area_title_edit);
            editNameView.setText(name);
            editNameView.setOnEditorActionListener(new OnEditorActionListener() {
                @Override
                public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                    area.setName(GPSFilterTextUtils.printName(getResources(), v.getText().toString()));
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
                    return false;
                }
            });
            editNameView.clearFocus();

            // Setup enabled switch.
            CompoundButton activatedSwitch = (CompoundButton) customView
                    .findViewById(R.id.edit_gpsfilter_area_toggle);
            activatedSwitch.setChecked(this.area.isEnabled());
            activatedSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    area.setEnabled(isChecked);
                }
            });
        } else {
            this.setTitle(name);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.edit_gpsfilter_area, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            finish();
            return true;

        case R.id.action_edit_gpsfilter_area_help:
            this.showSplash();
            return true;

        case R.id.action_edit_gpsfilter_area_rename:
            this.showRenameDialog();
            return true;

        case R.id.action_edit_gpsfilter_area_clear:
            this.clearPoints();
            return true;

        case R.id.action_edit_gpsfilter_area_undo:
            this.undoLastPoint();
            return true;

        case R.id.action_edit_gpsfilter_area_remove:
            this.removeArea();
            return true;

        case R.id.action_edit_gpsfilter_area_zoom:
            this.moveCameraToPolygon(true);
            return true;

        case R.id.action_gpsfilter_settings:
            this.gotoSettings();
            return true;

        default:
            return super.onOptionsItemSelected(item);
        }
    }

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

        this.setContentView(R.layout.activity_edit_gpsfilter_area);

        this.setupMap();

        this.fetchArea();

        if (this.isConsideredFresh()) {
            this.moveToCurrentLocation();
        }

        this.setupActionBar();

        this.setupMarkers();

        this.setupSplash();

        this.setupModeSpinner();

        this.setupBottomUndo();

        this.area.getMessageBus().subscribe(this);
    }

    /**
     * Moves the user to global options > location filter.
     */
    private void gotoSettings() {
        Intent i = new Intent(this, GlobalSettingsActivity.class);
        this.startActivity(i);
    }

    /**
     * Moves the user to its current location.
     */
    private void moveToCurrentLocation() {
        GPSFilterLocationRetriever retriever = new GPSFilterLocationRetriever(new Criteria());
        Location loc = retriever.getLocation(this);

        if (loc == null) {
            // User turned off GPS, send it to device location settings.
            Intent i = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            this.startActivity(i);
        } else {
            // First move to the last known location..
            this.moveCameraToLocation(loc, false);

            // Check if location fix is out dated, if it is, request a new location, ONCE.
            long elapsedTime = System.currentTimeMillis() - loc.getTime();
            if (elapsedTime > MAX_LOCATION_FIX_AGE) {
                // Therefore, we request a single fix.
                retriever.requestSingleUpdate(this, new LocationAdapter() {
                    @Override
                    public void onLocationChanged(Location loc) {
                        moveCameraToLocation(loc, true);
                    }
                });
            }
        }
    }

    /**
     * Prints the name of area to a human readable form.
     *
     * @return the area.
     */
    private String printName() {
        return GPSFilterTextUtils.printName(this.getResources(), this.area.getName());
    }

    /**
     * Handles a change in area via event.
     *
     * @param evt the change event.
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    @Handler
    public void handleAreaChange(GPSFilterArea.ChangeEvent evt) {
        switch (evt.getModifiedField()) {
        case ENABLED:
            if (Build.VERSION.SDK_INT >= 11) {
                CompoundButton activatedSwitch = (CompoundButton) this.getActionBar().getCustomView()
                        .findViewById(R.id.edit_gpsfilter_area_toggle);
                activatedSwitch.setChecked(evt.getArea().isEnabled());
            }
            break;

        case NAME:
            String name = this.printName();
            if (Build.VERSION.SDK_INT >= 11) {
                ((EditText) this.getActionBar().getCustomView().findViewById(R.id.edit_gpsfilter_area_title_edit))
                        .setText(name);
            } else {
                this.setTitle(name);
            }
            break;

        case MODE:
            break;

        case POLYGON:
        default:
            break;
        }
    }

    /**
     * Sets up the "action-bar" at the bottom undo button.
     */
    private void setupBottomUndo() {
        this.findViewById(R.id.action_edit_gpsfilter_area_undo_button).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                undoLastPoint();
            }
        });
    }

    /**
     * Sets up the markers if available.
     */
    private void setupMarkers() {
        GPSFilterPolygon polygon = this.area.getPolygon();

        if (polygon != null) {
            final LatLngBounds.Builder builder = LatLngBounds.builder();

            // Put markers for each edge.
            for (GPSLatLng pos : polygon.getPoints()) {
                LatLng point = this.convertLatLng(pos);

                builder.include(point);

                this.addMarker(point);
            }

            // Add listener that moves camera so that all markers are in users view.
            this.googleMap.setOnCameraChangeListener(new OnCameraChangeListener() {
                @Override
                public void onCameraChange(CameraPosition arg0) {
                    // Move camera.
                    moveCameraToPolygon(builder, false);

                    // Remove listener to prevent position reset on camera move.
                    googleMap.setOnCameraChangeListener(null);
                }
            });

            this.updateGuiPolygon();
        }
    }

    /**
     * Converts from model {@link GPSLatLng} to {@link LatLng}
     *
     * @param pos the model object.
     * @return google:s version.
     */
    private LatLng convertLatLng(GPSLatLng pos) {
        return new LatLng(pos.getLat(), pos.getLng());
    }

    /**
     * Moves the camera to a given a Location.
     *
     * @param loc the Location object to use for location.
     * @param animate whether or not to animate the movement.
     */
    private void moveCameraToLocation(Location loc, boolean animate) {
        LatLng pos = new LatLng(loc.getLatitude(), loc.getLongitude());
        CameraUpdate update = CameraUpdateFactory.newLatLngZoom(pos, MAP_MY_LOCATION_ZOOM);
        this.cameraAnimateOrMove(update, animate);
    }

    /**
     * Moves and zooms the camera so that all the markers are visible in users view.
     *
     * @param builder the builder containing to use for making bounds.
     */
    private void moveCameraToPolygon(boolean animate) {
        if (this.markers.isEmpty()) {
            return;
        }

        final LatLngBounds.Builder builder = LatLngBounds.builder();
        for (GPSLatLng pos : this.area.getPolygon().getPoints()) {
            builder.include(this.convertLatLng(pos));
        }

        this.moveCameraToPolygon(builder, animate);
    }

    /**
     * Moves and zooms the camera so that all the markers are visible in users view.
     *
     * @param builder the builder containing to use for making bounds.
     */
    private void moveCameraToPolygon(LatLngBounds.Builder builder, boolean animate) {
        CameraUpdate update = CameraUpdateFactory.newLatLngBounds(builder.build(), this.computeMoveCameraPadding());
        this.cameraAnimateOrMove(update, animate);
    }

    /**
     * Computes the padding to use when moving camera to polygon.
     *
     * @return the padding.
     */
    private int computeMoveCameraPadding() {
        Point dim = this.getScreenDim();
        int min = Math.min(dim.x, dim.y);
        return (int) (CAMERA_MOVE_BOUNDS_PADDING * min);
    }

    /**
     * Returns the screen dimensions as a Point.
     *
     * @return the screen dimensions.
     */
    private Point getScreenDim() {
        Display display = this.getWindowManager().getDefaultDisplay();

        @SuppressWarnings("deprecation")
        Point size = new Point(display.getWidth(), display.getHeight());
        return size;
    }

    /**
     * Moves or animates the camera with update.
     *
     * @param update the camera update to perform.
     * @param animate whether or not to animate, otherwise it instantaneously moves.
     */
    private void cameraAnimateOrMove(CameraUpdate update, boolean animate) {
        if (animate) {
            this.googleMap.animateCamera(update);
        } else {
            this.googleMap.moveCamera(update);
        }
    }

    /**
     * Fetches the area from set.
     */
    private void fetchArea() {
        // Fetch the isNew.
        Intent i = this.getIntent();
        this.isNew = i.getBooleanExtra(EXTRAS_AREA_IS_NEW, true);

        // Fetch ID.
        int id = i.getIntExtra(EXTRAS_AREA_ID, -1);
        if (id == -1) {
            Toast.makeText(this, "No area ID provided, finishing!", Toast.LENGTH_LONG).show();
            this.finish();
        }

        // Get the set from application.
        this.set = SFApplication.get().getGPSSet();

        // For some weird reason, NullPointerException will happen if we don't do this.
        this.set.setMessageBus(SFApplication.get().getBus());

        // Find area in set.
        this.area = this.set.getById(id);

        Log.d(TAG, "Fetched area " + this.area);

        if (this.area == null) {
            Toast.makeText(this, "The area ID provided did not exist in set.", Toast.LENGTH_LONG).show();
            this.finish();
        }
    }

    /**
     * Removes the current area, finishes activity.
     */
    private void removeArea() {
        this.set.remove(this.area);
        this.finish();
    }

    /**
     * Sets up the spinner for modes.
     */
    private void setupModeSpinner() {
        Spinner spinner = (Spinner) this.findViewById(R.id.action_edit_gpsfilter_area_mode);
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
                R.array.action_edit_gpsfilter_area_mode, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);

        spinner.setSelection(this.area.getMode() == GPSFilterMode.INCLUDE ? 0 : 1);

        spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                updateMode(position);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
    }

    /**
     * Updates the mode from slider position.
     *
     * @param position the position in array, 0 == Include, 1 == exclude.
     */
    protected void updateMode(int position) {
        GPSFilterMode mode = position == 0 ? GPSFilterMode.INCLUDE : GPSFilterMode.EXCLUDE;
        this.area.setMode(mode);
        this.updateGuiPolygon();
    }

    /**
     * Shows a rename dialog.
     */
    private void showRenameDialog() {
        AlertDialog.Builder alert = new AlertDialog.Builder(this);

        alert.setTitle(this.getString(R.string.action_edit_gpsfilter_area_rename));

        final EditText input = new EditText(this);
        input.setText(this.area.getName());
        alert.setView(input);

        alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                area.setName(input.getText().toString());
            }
        });

        alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
            }
        });

        alert.show();
    }

    /**
     * Sets up the help splash.
     */
    private void setupSplash() {
        this.splashInfoContainer = (LinearLayout) this.findViewById(R.id.edit_gpsfilter_area_splash);

        TextView textView = (TextView) this.splashInfoContainer.findViewById(R.id.edit_gpsfilter_area_splash_text);
        textView.setText(Html.fromHtml(this.getString(R.string.edit_gpsfilter_area_splash_text)));

        textView.setMovementMethod(new ScrollingMovementMethod());

        // Define fade out animation.
        this.splashFadeOut = new AlphaAnimation(1.00f, 0.00f);
        this.splashFadeOut.setDuration(SPLASH_FADE_DELAY);
        this.splashFadeOut.setAnimationListener(new AnimationListener() {
            public void onAnimationStart(Animation animation) {
            }

            public void onAnimationRepeat(Animation animation) {
            }

            public void onAnimationEnd(Animation animation) {
                splashInfoContainer.setVisibility(View.GONE);
            }
        });

        // Don't show if not new and we got polygon.
        if (!this.isConsideredFresh()) {
            this.splashInfoContainer.setVisibility(View.GONE);
        }
    }

    /**
     * Returns whether or not this activity instance is considered<br/>
     * fresh. It is fresh when the area is either new, or the polygon is undefined.
     *
     * @return true if new & undefined polygon.
     */
    private boolean isConsideredFresh() {
        return this.isNew || this.area.getPolygon() == null;
    }

    /**
     * Shows the help splash.
     */
    private void showSplash() {
        this.splashInfoContainer.setVisibility(View.VISIBLE);
    }

    /**
     * Hides the help splash.
     */
    private void hideSplash() {
        this.splashInfoContainer.startAnimation(this.splashFadeOut);
    }

    /**
     * Adds a point to polygon at point.<br/>
     * Also adds a marker to GUI.
     *
     * @param point the point to add to polygon and where to place marker.
     */
    private void addPoint(LatLng point) {
        this.addMarker(point);
        this.commitPolygon();
    }

    /**
     * Adds a marker on map at point.
     *
     * @param point the point to add maker at.
     */
    private void addMarker(LatLng point) {
        this.markers.add(this.googleMap.addMarker(this.makeMarkerAt(point)));
    }

    /**
     * Makes a marker at point.
     *
     * @param point the point in LatLng.
     * @return the marker.
     */
    private MarkerOptions makeMarkerAt(LatLng point) {
        return new MarkerOptions().flat(true).draggable(true).position(point);
    }

    /**
     * Removes the last added marker/point.
     */
    private void undoLastPoint() {
        if (this.markers.isEmpty()) {
            return;
        }

        this.markers.remove(this.markers.size() - 1).remove();
        this.commitPolygon();

        if (this.markers.size() > 1) {
            this.moveCameraToPolygon(true);
        }

        this.disableIfDissatisfied();
    }

    /**
     * Whether or not the current markers satisfy being a polygon (having 3 edges / markers).
     *
     * @return true if it satisfies being a polygon.
     */
    private boolean satisfiesPolygon() {
        return this.markers.size() >= 3;
    }

    /**
     * Clears all markers/points.
     */
    private void clearPoints() {
        for (Marker marker : this.markers) {
            marker.remove();
        }

        this.markers.clear();
        this.commitPolygon();
        this.disableIfDissatisfied();
    }

    /**
     * Disables the area when/if dissatisfied.
     */
    private void disableIfDissatisfied() {
        if (!this.satisfiesPolygon()) {
            this.area.setEnabled(false);
        }
    }

    /**
     * Commits the polygon saving it while also performing a GUI update.<br/>
     * If the polygon doesn't honor {@link #satisfiesPolygon()}, the area is disabled.
     */
    private void commitPolygon() {
        this.updateGuiPolygon();
        this.area.setPolygon(this.toFilterPolygon());
    }

    /**
     * Converts the list of markers to a {@link GPSFilterPolygon}.
     *
     * @return the filter polygon object.
     */
    private GPSFilterPolygon toFilterPolygon() {
        if (this.markers.isEmpty()) {
            return null;
        } else {
            List<GPSLatLng> points = Lists.newArrayListWithCapacity(this.markers.size());
            for (Marker marker : this.markers) {
                LatLng pos = marker.getPosition();
                points.add(new GPSLatLng(pos.latitude, pos.longitude));
            }

            return new GPSFilterPolygon(points);
        }
    }

    /**
     * Updates the GUI polygon, removing the old one,<br/>
     * adding a new one if we have >= 3 points.
     */
    private void updateGuiPolygon() {
        if (this.poly != null) {
            this.poly.remove();
        }

        // A polygon is at minimum a triangle.
        if (!this.satisfiesPolygon()) {
            return;
        }

        PolygonOptions options = new PolygonOptions();
        options.geodesic(POLYGON_GEODESIC).strokeWidth(2).fillColor(this.getFillColor())
                .strokeColor(this.getResources().getColor(POLYGON_STROKE_COLOR));

        for (Marker marker : this.markers) {
            options.add(marker.getPosition());
        }

        this.poly = this.googleMap.addPolygon(options);
    }

    /**
     * Returns the fill-color to use.
     *
     * @return the color value.
     */
    private int getFillColor() {
        int id = this.area.getMode() == GPSFilterMode.INCLUDE ? POLYGON_INCLUDE_FILL_COLOR
                : POLYGON_EXCLUDE_FILL_COLOR;
        return adjustAlpha(this.getResources().getColor(id), 255 * 0.5f);
    }

    /**
     * Sets up the map.
     */
    private void setupMap() {
        this.markers = Lists.newArrayList();

        int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getBaseContext());
        if (status != ConnectionResult.SUCCESS) {
            // Google Play Services are not available.
            int requestCode = 10;
            GooglePlayServicesUtil.getErrorDialog(status, this, requestCode).show();
        } else {
            // Google Play Services are available.
            if (this.googleMap == null) {
                FragmentManager fragManager = this.getSupportFragmentManager();
                SupportMapFragment mapFrag = (SupportMapFragment) fragManager
                        .findFragmentById(R.id.edit_gpsfilter_area_google_map);
                this.googleMap = mapFrag.getMap();

                if (this.googleMap != null) {
                    // The Map is verified. It is now safe to manipulate the map.
                    this.configMap();
                }
            }
        }
    }

    /**
     * Configures the map.
     */
    private void configMap() {
        // Enable all gestures.
        this.googleMap.getUiSettings().setAllGesturesEnabled(true);

        // Add button for my location.
        this.googleMap.setMyLocationEnabled(true);

        // Bind events for markers.
        this.googleMap.setOnMapClickListener(this);
        this.googleMap.setOnMarkerDragListener(this);
        this.googleMap.setOnMarkerClickListener(this);
    }

    @Override
    public void onMapClick(LatLng point) {
        if (this.splashInfoContainer.getVisibility() == View.VISIBLE) {
            this.hideSplash();
        } else {
            this.addPoint(point);
        }
    }

    @Override
    public void onMarkerDrag(Marker marker) {
        this.updateGuiPolygon();
    }

    @Override
    public void onMarkerDragEnd(Marker marker) {
        this.commitPolygon();
    }

    @Override
    public void onMarkerDragStart(Marker marker) {
    }

    @Override
    public boolean onMarkerClick(final Marker marker) {
        return false;
    }

    /**
     * Alpha-adjusts a given color setting the alpha-component to alphaArg, rounded.
     *
     * @param color the color.
     * @param alphaArg the alpha value to use.
     * @return the color.
     */
    private int adjustAlpha(int color, float alphaArg) {
        int alpha = Math.round(alphaArg);
        int red = Color.red(color);
        int green = Color.green(color);
        int blue = Color.blue(color);
        return Color.argb(alpha, red, green, blue);
    }
}