ru.neverdark.phototools.azimuth.PluginActivity.java Source code

Java tutorial

Introduction

Here is the source code for ru.neverdark.phototools.azimuth.PluginActivity.java

Source

/*******************************************************************************
 * Copyright (C) 2014-2015 Artem Yankovskiy (artemyankovskiy@gmail.com).
 *      This program 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.
 *
 *      This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package ru.neverdark.phototools.azimuth;

import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.CardView;
import android.support.v7.widget.SearchView;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;

import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;

import ru.neverdark.abs.OnCallback;
import ru.neverdark.abs.UfoFragmentActivity;
import ru.neverdark.phototools.azimuth.async.AsyncCalculator;
import ru.neverdark.phototools.azimuth.async.AsyncGeoCoder;
import ru.neverdark.phototools.azimuth.db.LocationRecord;
import ru.neverdark.phototools.azimuth.db.LocationsAdapter;
import ru.neverdark.phototools.azimuth.dialogs.ConfirmDialog;
import ru.neverdark.phototools.azimuth.dialogs.DateTimeDialog;
import ru.neverdark.phototools.azimuth.dialogs.MessageDialog;
import ru.neverdark.phototools.azimuth.dialogs.SaveLocationDialog;
import ru.neverdark.phototools.azimuth.dialogs.ZonePickerDialog;
import ru.neverdark.phototools.azimuth.model.MapApi;
import ru.neverdark.phototools.azimuth.model.SunCalculator;
import ru.neverdark.phototools.azimuth.utils.Common;
import ru.neverdark.phototools.azimuth.utils.Constants;
import ru.neverdark.phototools.azimuth.utils.Log;
import ru.neverdark.phototools.azimuth.utils.Settings;

/**
 * Main application activity
 */
public class PluginActivity extends UfoFragmentActivity {
    private static final int RESULT_SETTINGS = 101;
    private ListView mLocationList;
    private Context mContext;
    private MenuItem mMenuItemSearch;
    private TimeZone mTimeZone;
    private Calendar mCalendar;
    private MenuItem mMenuItemTZ;
    private MenuItem mMenuSave;
    private LocationsAdapter mAdapter;
    private LocationRecord mLocationRecord;
    private CardView mMapInfoCard;
    private TextView mSunInfoTv;
    private TextView mSunriseInfoTv;
    private TextView mSunsetInfoTv;
    private View mSunInfo;
    private View mSunriseInfo;
    private View mSunsetInfo;
    private View mSunAltitudeInfo;
    private TextView mSunAltitudeTv;
    private TextView mSunInfoTvName;
    private TextView mSunriseInfoTvName;
    private TextView mSunsetInfoTvName;

    private static int getContrastVersionForColor(int color) {
        double y = (299 * Color.red(color) + 587 * Color.green(color) + 114 * Color.blue(color)) / 1000;
        return y >= 128 ? Color.BLACK : Color.WHITE;
    }

    @Override
    public void bindObjects() {
        mContext = this;
        SupportMapFragment mMapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mMapFragment.getMapAsync(MapApi.getInstance(mContext));
        setDrawerLayout((DrawerLayout) findViewById(R.id.drawer_layout));
        setDrawerToggle(
                new ActionBarDrawerToggle(this, getDrawerLayout(), R.string.open_drawer, R.string.close_drawer));
        mLocationList = (ListView) findViewById(R.id.location_list);

        mMapInfoCard = (CardView) findViewById(R.id.map_info_card);
        mSunInfoTv = (TextView) findViewById(R.id.map_sun_tv);
        mSunInfoTvName = (TextView) findViewById(R.id.map_sun_tv_name);
        mSunInfo = findViewById(R.id.map_sun);
        mSunriseInfo = findViewById(R.id.map_sunrise);
        mSunsetInfo = findViewById(R.id.map_sunset);
        mSunriseInfoTv = (TextView) findViewById(R.id.map_sunrise_tv);
        mSunriseInfoTvName = (TextView) findViewById(R.id.map_sunrise_tv_name);
        mSunsetInfoTv = (TextView) findViewById(R.id.map_sunset_tv);
        mSunsetInfoTvName = (TextView) findViewById(R.id.map_sunset_tv_name);
        mSunAltitudeInfo = findViewById(R.id.map_altitude);
        mSunAltitudeTv = (TextView) findViewById(R.id.map_altitude_tv);
    }

    @Override
    public void onDestroy() {
        Log.enter();
        MapApi.freeInstance();
        super.onDestroy();
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.locations, menu);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
        LocationRecord record = mAdapter.getItem(info.position);
        switch (item.getItemId()) {
        case R.id.remove_location:
            showRemoveLocationDialog(record);
            return true;
        }

        return super.onContextItemSelected(item);
    }

    private void showRemoveLocationDialog(LocationRecord record) {
        ConfirmDialog dialog = ConfirmDialog.getInstance(mContext);
        String message = String.format(getString(R.string.deleteConfirmationDialog_message),
                record.getLocationName());
        dialog.setMessage(message);
        dialog.setCallback(new RemoveLocationListener(record));
        dialog.show(getSupportFragmentManager(), ConfirmDialog.DIALOG_ID);
    }

    @Override
    public void setListeners() {
        MapApi.getInstance(mContext).setCallback(new MapListener());
        getDrawerLayout().setDrawerListener(getDrawerToggle());
        mLocationList.setOnItemClickListener(new LocationListClickListener());
        registerForContextMenu(mLocationList);
        mMapInfoCard.setOnClickListener(new CardInfoClickListener());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        Log.enter();

        getMenuInflater().inflate(R.menu.main, menu);

        mMenuItemSearch = menu.findItem(R.id.item_search);
        mMenuItemTZ = menu.findItem(R.id.item_timeZone);
        mMenuSave = menu.findItem(R.id.item_saveLocation);

        if (Constants.PAID) {
            SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
            SearchView searchView = (SearchView) MenuItemCompat.getActionView(mMenuItemSearch);
            searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
            searchView.setIconifiedByDefault(true);
            searchView.setQueryHint(getString(R.string.search_hint));
            searchView.setOnQueryTextListener(new QueryTextListener());
        } else {
            MenuItemCompat.setActionView(mMenuItemSearch, null);
        }
        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        Log.enter();
        mMenuItemTZ.setVisible(!Settings.isInternetTimeZone(mContext));
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            if (getDrawerToggle().isDrawerIndicatorEnabled()) {
                if (getDrawerLayout().isDrawerOpen(mLocationList)) {
                    getDrawerLayout().closeDrawer(mLocationList);
                } else {
                    getDrawerLayout().openDrawer(mLocationList);
                }
            }
            break;
        case R.id.item_search:
            if (!Constants.PAID) {
                gotoDonate();
                break;
            }
            break;
        case R.id.item_map_normal:
            MapApi.getInstance(mContext).setMapType(GoogleMap.MAP_TYPE_NORMAL);
            break;
        case R.id.item_map_hybrid:
            MapApi.getInstance(mContext).setMapType(GoogleMap.MAP_TYPE_HYBRID);
            break;
        case R.id.item_map_satellite:
            MapApi.getInstance(mContext).setMapType(GoogleMap.MAP_TYPE_SATELLITE);
            break;
        case R.id.item_map_terrain:
            MapApi.getInstance(mContext).setMapType(GoogleMap.MAP_TYPE_TERRAIN);
            break;
        case R.id.item_settings:
            Intent settings = new Intent(this, SettingsActivity.class);
            startActivityForResult(settings, RESULT_SETTINGS);
            break;
        case R.id.item_rate:
            showRate();
            break;
        case R.id.item_feedback:
            showFeedback();
            break;
        case R.id.item_dateTime:
            showDateTimeDialog();
            break;
        case R.id.item_timeZone:
            showZonePickerDialog();
            break;
        case R.id.item_saveLocation:
            showSaveLocationDialog();
            break;
        }

        return true;
    }

    private void showSaveLocationDialog() {
        if (Constants.PAID) {
            if (mLocationRecord == null) {
                mLocationRecord = new LocationRecord();
            }

            if (getSupportActionBar().getSubtitle() != null) {
                mLocationRecord.setLocationName(getSupportActionBar().getSubtitle().toString());
            }
            MapApi.getInstance(mContext).mapToLocation(mLocationRecord);
            SaveLocationDialog dialog = SaveLocationDialog.getInstance(mContext, mLocationRecord);
            dialog.setCallback(new SaveLocationListener());
            dialog.show(getSupportFragmentManager(), SaveLocationDialog.DIALOG_ID);
        } else {
            gotoDonate();
        }
    }

    private void showZonePickerDialog() {
        ZonePickerDialog dialog = ZonePickerDialog.getInstance(mContext);
        dialog.setCallback(new ZonePickerListener());
        dialog.show(getSupportFragmentManager(), ZonePickerDialog.DIALOG_TAG);
    }

    private void showDateTimeDialog() {
        DateTimeDialog dialog = DateTimeDialog.getInstance(mContext, mCalendar);
        dialog.setCallback(new DateTimeDialogListener());
        dialog.show(getSupportFragmentManager(), DateTimeDialog.DIALOG_ID);
    }

    private void showFeedback() {
        Intent mailIntent = new Intent(Intent.ACTION_SEND);
        mailIntent.setType("plain/text");
        mailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] { getString(R.string.author_email) });
        mailIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.app_name));
        startActivity(Intent.createChooser(mailIntent, getString(R.string.chooseEmailApp)));
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.plugin_activity);
        bindObjects();
        setListeners();

        if (Constants.PAID) {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            getSupportActionBar().setHomeButtonEnabled(true);
        }

        mCalendar = Calendar.getInstance();
        mAdapter = new LocationsAdapter(mContext);
        mLocationList.setAdapter(mAdapter);
        int title = Constants.PAID ? R.string.app_title : R.string.app_title_free;
        setTitle(title);
    }

    private void gotoDonate() {
        Common.openPaidMarketUrl(mContext);
    }

    @Override
    public void onResume() {
        Log.enter();
        super.onResume();
        if (!Constants.PAID) {
            getDrawerLayout().setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
        }
        if (Settings.isShowTip(mContext)) {
            Common.showMessage(mContext, R.string.startupHint);
        }

        mAdapter.openDb();
    }

    private void showErrorDialog(String errorText) {
        MessageDialog dialog = MessageDialog.getInstance(mContext);
        dialog.setMessages(getString(R.string.errorDialog_title), errorText);
        dialog.show(getSupportFragmentManager(), MessageDialog.DIALOG_ID);
    }

    @Override
    public void onPause() {
        if (Constants.PAID) {
            MapApi.getInstance(mContext).saveState();
        }

        mAdapter.closeDb();
        super.onPause();
    }

    private void showRate() {
        Common.openMarketUrl(mContext, mContext.getPackageName());
    }

    private void calculate(LatLng location) {
        boolean isInternetTimezone = Settings.isInternetTimeZone(mContext);
        AsyncCalculator asyncCalc = new AsyncCalculator(this, new CalculationResultListener());
        asyncCalc.setIsInternetTimeZone(isInternetTimezone);
        asyncCalc.setTimeZone(mTimeZone);
        asyncCalc.setLocation(location);
        asyncCalc.setCalendar(mCalendar);
        asyncCalc.execute();
    }

    private void recalculate() {
        MapApi api = MapApi.getInstance(mContext);
        if (api.isHaveMarkder()) {
            calculate(api.getMarkerLocation());
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        switch (requestCode) {
        case RESULT_SETTINGS:
            recalculate();
            break;
        }
    }

    private class LocationListClickListener implements android.widget.AdapterView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            getDrawerLayout().closeDrawer(mLocationList);
            mLocationRecord = mAdapter.getItem(position);
            mAdapter.updateAccessTime(mLocationRecord);
            MapApi.getInstance(mContext).locationToMap(mLocationRecord);
            calculate(MapApi.getInstance(mContext).getMarkerLocation());
            getSupportActionBar().setSubtitle(mLocationRecord.getLocationName());
            mMenuSave.setVisible(true);
        }
    }

    private class QueryTextListener implements SearchView.OnQueryTextListener {

        private void startSearchProcess(String query) {
            AsyncGeoCoder geoCoder = new AsyncGeoCoder(mContext, query);
            geoCoder.setCallback(new GeoCoderListener());
            geoCoder.execute();
        }

        @Override
        public boolean onQueryTextSubmit(String query) {
            MenuItemCompat.collapseActionView(mMenuItemSearch);
            startSearchProcess(query);
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {

            return false;
        }

        private class GeoCoderListener implements AsyncGeoCoder.OnGeoCoderListener {
            @Override
            public void onGetResultFail() {
                showErrorDialog(getString(R.string.error_geoCoderNotAvailable));
            }

            @Override
            public void onGetResultSuccess(LatLng coordinates, String searchString) {
                if (coordinates != null) {
                    mLocationRecord = null;
                    getSupportActionBar().setSubtitle(searchString);
                    mMapInfoCard.setVisibility(View.GONE);
                    MapApi.getInstance(mContext).moveCamera(coordinates);
                } else {
                    String error = String.format(getString(R.string.error_notFound), searchString);
                    showErrorDialog(error);
                }
            }
        }
    }

    private class MapListener implements MapApi.OnMapListener {
        @Override
        public void onMapLongClick(LatLng latLng) {
            calculate(latLng);
            mMenuSave.setVisible(true);
        }
    }

    private class CalculationResultListener implements AsyncCalculator.OnCalculationResultListener {
        @Override
        public void onGetResultFail() {
            showErrorDialog(getString(R.string.error_timeZoneIsNotDefined));
        }

        @Override
        public void onGetResultSuccess(SunCalculator.CalculationResult calculationResult) {
            int color = 0;
            int contrast = 0;
            double altitude = calculationResult.getAltitude();
            double azimuth = calculationResult.getAzimuth();
            double sunsetAzimuth = calculationResult.getSunsetAzimuth();
            double sunriseAzimuth = calculationResult.getSunriseAzimuth();

            MapApi.getInstance(mContext).setAzimuthData(altitude, azimuth, sunsetAzimuth, sunriseAzimuth);
            MapApi.getInstance(mContext).drawAzimuth(calculationResult.getLocation());

            if (altitude < 0) {
                showErrorDialog(getString(R.string.error_noSun));
            }

            if (altitude >= 0 || Settings.isSunsetShow(mContext) || Settings.isSunriseShow(mContext)) {
                mMapInfoCard.setVisibility(View.VISIBLE);
            } else {
                mMapInfoCard.setVisibility(View.GONE);
            }

            if (altitude >= 0) {
                color = Settings.getSunLineColor(mContext);
                contrast = getContrastVersionForColor(color);
                mSunInfo.setBackgroundColor(color);
                mSunInfo.setVisibility(View.VISIBLE);
                mSunInfoTv.setText(calculationResult.getTime());
                mSunInfoTv.setTextColor(contrast);
                mSunInfoTvName.setTextColor(contrast);
            } else {
                mSunInfo.setVisibility(View.GONE);
            }

            if (Settings.isSunsetShow(mContext)) {
                color = Settings.getSunsetLineColor(mContext);
                contrast = getContrastVersionForColor(color);
                mSunsetInfo.setBackgroundColor(color);
                mSunsetInfo.setVisibility(View.VISIBLE);
                mSunsetInfoTv.setText(calculationResult.getSunsetTime());
                mSunsetInfoTv.setTextColor(contrast);
                mSunsetInfoTvName.setTextColor(contrast);
            } else {
                mSunsetInfo.setVisibility(View.GONE);
            }

            if (Settings.isSunriseShow(mContext)) {
                color = Settings.getSunriseLineColor(mContext);
                contrast = getContrastVersionForColor(color);
                mSunriseInfo.setBackgroundColor(color);
                mSunriseInfo.setVisibility(View.VISIBLE);
                mSunriseInfoTv.setText(calculationResult.getSunriseTime());
                mSunriseInfoTv.setTextColor(contrast);
                mSunriseInfoTvName.setTextColor(contrast);
            } else {
                mSunriseInfo.setVisibility(View.GONE);
            }

            if (Settings.isAltitudeShow(mContext) && altitude >= 0) {
                mSunAltitudeInfo.setVisibility(View.VISIBLE);
                mSunAltitudeTv.setText(String.format(Locale.US, "%.3f", calculationResult.getAltitude()));
            } else {
                mSunAltitudeInfo.setVisibility(View.GONE);
            }
        }
    }

    private class DateTimeDialogListener implements DateTimeDialog.OnPositiveClickListener, OnCallback {
        @Override
        public void onPositiveClick(Calendar calendar) {
            mCalendar = calendar;
            recalculate();
        }
    }

    private class ZonePickerListener implements ZonePickerDialog.OnPositiveClickListener, OnCallback {
        @Override
        public void onPositiveClick(TimeZone tz) {
            mTimeZone = tz;
            recalculate();
        }
    }

    private class SaveLocationListener implements SaveLocationDialog.OnPositiveClickListener, OnCallback {
        @Override
        public void onPositiveClick(LocationRecord data) {
            getSupportActionBar().setSubtitle(data.getLocationName());
            if (data.getId() == -1L) {
                mAdapter.addItem(data);
            } else {
                if (mAdapter.isLocationExists(data)) {
                    mAdapter.updateItem(data);
                } else {
                    mAdapter.addItem(data);
                }
            }
        }
    }

    private class RemoveLocationListener implements ConfirmDialog.OnPositiveClickListener, OnCallback {
        private final LocationRecord mRecord;

        public RemoveLocationListener(LocationRecord record) {
            mRecord = record;
        }

        @Override
        public void onPositiveClickHandler() {
            mAdapter.removeItem(mRecord);
        }
    }

    private class CardInfoClickListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            showDateTimeDialog();
        }
    }
}