com.wmstein.transektcount.CountOptionsActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.wmstein.transektcount.CountOptionsActivity.java

Source

package com.wmstein.transektcount;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.Toast;

import com.wmstein.transektcount.database.Alert;
import com.wmstein.transektcount.database.AlertDataSource;
import com.wmstein.transektcount.database.Count;
import com.wmstein.transektcount.database.CountDataSource;
import com.wmstein.transektcount.widgets.AddAlertWidget;
import com.wmstein.transektcount.widgets.AlertCreateWidget;
import com.wmstein.transektcount.widgets.EditNotesWidget;
import com.wmstein.transektcount.widgets.OptionsWidget;

import java.util.ArrayList;
import java.util.List;

/************************************************************
 * Edit options for counting species
 * uses optionsWidget.java and widget_options.xml
 * Supplemented with functions for transect external counter
 * Based on CountOptionsActivity.java by milo on 05/05/2014.
 * Changed by wmstein on 18.02.2016
 */
public class CountOptionsActivity extends AppCompatActivity
        implements SharedPreferences.OnSharedPreferenceChangeListener {
    private static String TAG = "transektcountCountOptionsActivity";
    TransektCountApplication transektCount;
    SharedPreferences prefs;

    private Count count;
    private int count_id;
    private List<Alert> alerts;
    private CountDataSource countDataSource;
    private AlertDataSource alertDataSource;
    private View markedForDelete;
    private int deleteAnAlert;
    private int section_id;

    private Bitmap bMap;
    private BitmapDrawable bg;

    LinearLayout static_widget_area;
    LinearLayout dynamic_widget_area;
    OptionsWidget curr_val_widget;
    EditNotesWidget enw;
    AddAlertWidget aa_widget;

    ArrayList<AlertCreateWidget> savedAlerts;

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

        transektCount = (TransektCountApplication) getApplication();
        prefs = com.wmstein.transektcount.TransektCountApplication.getPrefs();
        prefs.registerOnSharedPreferenceChangeListener(this);
        boolean brightPref = prefs.getBoolean("pref_bright", true);

        // Set full brightness of screen
        if (brightPref) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
            WindowManager.LayoutParams params = getWindow().getAttributes();
            params.screenBrightness = 1.0f;
            getWindow().setAttributes(params);
        }

        ScrollView counting_screen = (ScrollView) findViewById(R.id.count_options);
        bMap = transektCount.decodeBitmap(R.drawable.kbackground, transektCount.width, transektCount.height);
        bg = new BitmapDrawable(counting_screen.getResources(), bMap);
        counting_screen.setBackground(bg);

        static_widget_area = (LinearLayout) findViewById(R.id.static_widget_area);
        dynamic_widget_area = (LinearLayout) findViewById(R.id.dynamic_widget_area);

        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            count_id = extras.getInt("count_id");
            section_id = extras.getInt("section_id");
        }

        savedAlerts = new ArrayList<>();
        if (savedInstanceState != null) {
            if (savedInstanceState.getSerializable("savedAlerts") != null) {
                savedAlerts = (ArrayList<AlertCreateWidget>) savedInstanceState.getSerializable("savedAlerts");
            }
        }
    }

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

        // build the count options screen
        // clear any existing views
        static_widget_area.removeAllViews();
        dynamic_widget_area.removeAllViews();

        // get the data sources
        countDataSource = new CountDataSource(this);
        countDataSource.open();
        alertDataSource = new AlertDataSource(this);
        alertDataSource.open();

        count = countDataSource.getCountById(count_id);
        getSupportActionBar().setTitle(count.name);

        List<Alert> alerts = alertDataSource.getAllAlertsForCount(count_id);

        // setup the static widgets in the following order
        // 1. Current count value (internal counter)
        // 2. Current counta value (external counter)
        // 3. Alert add/remove
        curr_val_widget = new OptionsWidget(this, null);
        curr_val_widget.setInstructions(String.format(getString(R.string.editCountValue), count.name, count.count));
        curr_val_widget
                .setInstructionsa(String.format(getString(R.string.editCountValuea), count.name, count.counta));
        curr_val_widget.setParameterValue(count.count);
        curr_val_widget.setParameterValuea(count.counta);
        static_widget_area.addView(curr_val_widget);

        enw = new EditNotesWidget(this, null);
        enw.setSectionNotes(count.notes);
        enw.setWidgetNotes(getString(R.string.notesSpecies));
        enw.setHint(getString(R.string.notesHint));
        enw.requestFocus();

        static_widget_area.addView(enw);

        aa_widget = new AddAlertWidget(this, null);
        static_widget_area.addView(aa_widget);

        /*
         * There should be a method to add all counts in order to re-draw when one is deleted.
         */
        for (Alert alert : alerts) {
            AlertCreateWidget acw = new AlertCreateWidget(this, null);
            acw.setAlertName(alert.alert_text);
            acw.setAlertValue(alert.alert);
            acw.setAlertId(alert.id);
            dynamic_widget_area.addView(acw);
        }

        /*
         * Add saved alert create widgets
         */
        for (AlertCreateWidget acw : savedAlerts) {
            dynamic_widget_area.addView(acw);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        /*
         * Before these widgets can be serialised they must be removed from their parent, or else
         * trying to add them to a new parent causes a crash because they've already got one.
         */
        super.onSaveInstanceState(outState);
        for (AlertCreateWidget acw : savedAlerts) {
            ((ViewGroup) acw.getParent()).removeView(acw);
        }
        outState.putSerializable("savedAlerts", savedAlerts);
    }

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

        // finally, close the database
        countDataSource.close();
        alertDataSource.close();

    }

    public void saveAndExit(View view) {
        saveData();
        savedAlerts.clear();
        super.finish();
    }

    public void saveData() {
        // don't crash if the user hasn't filled things in...
        Toast.makeText(CountOptionsActivity.this, getString(R.string.sectSaving) + " " + count.name + "!",
                Toast.LENGTH_SHORT).show();
        count.counta = curr_val_widget.getParameterValuea();
        count.count = curr_val_widget.getParameterValue();
        count.notes = enw.getSectionNotes();

        countDataSource.saveCount(count);

        /*
         * Get all the alerts from the dynamic_widget_area and save each one.
         * If it has an id value set to anything higher than 0 then it should be an update, if it is 0
         * then it's a new alert and should be created instead.
         */
        int childcount = dynamic_widget_area.getChildCount();
        for (int i = 0; i < childcount; i++) {
            AlertCreateWidget acw = (AlertCreateWidget) dynamic_widget_area.getChildAt(i);
            if (isNotEmpty(acw.getAlertName())) {
                // save or create
                if (acw.getAlertId() == 0) {
                    alertDataSource.createAlert(count_id, acw.getAlertValue(), acw.getAlertName());
                } else {
                    alertDataSource.saveAlert(acw.getAlertId(), acw.getAlertValue(), acw.getAlertName());
                }
            } else {
                Log.i(TAG, "Failed to save alert: " + acw.getAlertId());
            }
        }
    }

    /*
     * Scroll to end of view
     * by wmstein
     */
    public void ScrollToEndOfView(View scrlV) {
        int scroll_amount = scrlV.getBottom();
        int scrollY = scroll_amount;
        boolean pageend = false;
        while (!pageend) {
            scrlV.scrollTo(0, scroll_amount); //scroll
            scroll_amount = scroll_amount + scroll_amount; //increase scroll_amount
            scrollY = scrollY + scrlV.getScrollY(); //scroll position of 1. row
            if (scroll_amount > scrollY) {
                pageend = true;
            }
        }
    }

    // Add alert to species counter
    public void addAnAlert(View view) {
        AlertCreateWidget acw = new AlertCreateWidget(this, null);
        savedAlerts.add(acw);
        // Scroll to end of view
        View scrollV = findViewById(R.id.count_options);
        ScrollToEndOfView(scrollV);
        acw.requestFocus();
        dynamic_widget_area.addView(acw);
    }

    // Delete alert from species counter and its widget from the view
    public void deleteWidget(View view) {
        /*
         * These global variables keep a track of the view containing an alert to be deleted and also the id
         * of the alert itself, to make sure that they're available inside the code for the alert dialog by
         * which they will be deleted.
         */
        AlertDialog.Builder areYouSure;
        markedForDelete = view;
        deleteAnAlert = (Integer) view.getTag();
        if (deleteAnAlert == 0) {
            //Log.i(TAG, "(1) View tag was " + String.valueOf(deleteAnAlert));
            // the actual AlertCreateWidget is two levels up from the button in which it is embedded
            dynamic_widget_area.removeView((AlertCreateWidget) view.getParent().getParent());
        } else {
            //Log.i(TAG, "(2) View tag was " + String.valueOf(deleteAnAlert));
            // before removing this widget it is necessary to do the following:
            // (1) Check the user is sure they want to delete it and, if so...
            // (2) Delete the associated alert from the database.
            areYouSure = new AlertDialog.Builder(this);
            areYouSure.setTitle(getString(R.string.deleteAlert));
            areYouSure.setMessage(getString(R.string.reallyDeleteAlert));
            areYouSure.setPositiveButton(R.string.yesDeleteIt, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                    // go ahead for the delete
                    try {
                        alertDataSource.deleteAlertById(deleteAnAlert);
                        dynamic_widget_area.removeView((AlertCreateWidget) markedForDelete.getParent().getParent());
                    } catch (Exception e) {
                        Log.i(TAG, "Failed to delete a widget: " + e.toString());
                    }
                }
            });
            areYouSure.setNegativeButton(R.string.noCancel, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                    // Cancelled.
                }
            });
            areYouSure.show();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.count_options, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.home) {
            Intent intent = NavUtils.getParentActivityIntent(this);
            intent.putExtra("section_id", section_id);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
            NavUtils.navigateUpTo(this, intent);
        } else if (id == R.id.menuSaveExit) {
            saveData();
            super.finish();
        }
        return super.onOptionsItemSelected(item);
    }

    public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
        ScrollView counting_screen = (ScrollView) findViewById(R.id.count_options);
        counting_screen.setBackground(null);
        bMap = transektCount.decodeBitmap(R.drawable.kbackground, transektCount.width, transektCount.height);
        bg = new BitmapDrawable(counting_screen.getResources(), bMap);
        counting_screen.setBackground(bg);
    }

    /**
     * Following functions are taken from the Apache commons-lang3-3.4 library
     * licensed under Apache License Version 2.0, January 2004
     *
     * Checks if a CharSequence is not empty ("") and not null.
     *
     * isNotEmpty(null)      = false
     * isNotEmpty("")        = false
     * isNotEmpty(" ")       = true
     * isNotEmpty("bob")     = true
     * isNotEmpty("  bob  ") = true
     *
     * @param cs  the CharSequence to check, may be null
     * @return {@code true} if the CharSequence is not empty and not null
     */
    public static boolean isNotEmpty(final CharSequence cs) {
        return !isEmpty(cs);
    }

    /**
     * Checks if a CharSequence is empty ("") or null.
     *
     * isEmpty(null)      = true
     * isEmpty("")        = true
     * isEmpty(" ")       = false
     * isEmpty("bob")     = false
     * isEmpty("  bob  ") = false
     *
     * @param cs  the CharSequence to check, may be null
     * @return {@code true} if the CharSequence is empty or null
     */
    public static boolean isEmpty(final CharSequence cs) {
        return cs == null || cs.length() == 0;
    }

}