com.wmstein.transektcount.EditSectionActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.wmstein.transektcount.EditSectionActivity.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.AlertDataSource;
import com.wmstein.transektcount.database.Count;
import com.wmstein.transektcount.database.CountDataSource;
import com.wmstein.transektcount.database.Section;
import com.wmstein.transektcount.database.SectionDataSource;
import com.wmstein.transektcount.widgets.CountEditWidget;
import com.wmstein.transektcount.widgets.EditNotesWidget;
import com.wmstein.transektcount.widgets.EditTitleWidget;

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

/*************************************************************************
 * Edit the current section list (change, delete) and insert new species
 * EditSectionActivity is called from CountingActivity.
 * Uses CountEditWidget.java, EditTitleWidget.java, EditNotesWidget.java,
 * activity_edit_section.xml, widget_edit_title.xml, widget_edit_notes.xml.
 * Based on EditProjectActivity.java by milo on 05/05/2014.
 * Changed by wmstein on 18.02.2016
 */
public class EditSectionActivity extends AppCompatActivity
        implements SharedPreferences.OnSharedPreferenceChangeListener {
    TransektCountApplication transektCount;
    SharedPreferences prefs;
    public static String TAG = "TransektCountEditSectionActivity";

    // the actual data
    Section section;
    List<Count> counts;

    private SectionDataSource sectionDataSource;
    private CountDataSource countDataSource;
    private AlertDataSource alertDataSource;

    int section_id;
    LinearLayout counts_area;
    LinearLayout notes_area;
    EditTitleWidget etw;
    EditNotesWidget enw;
    private View markedForDelete;
    private int idToDelete;
    AlertDialog.Builder areYouSure;

    public ArrayList<String> countNames;
    public ArrayList<String> countCodes;
    public ArrayList<String> cmpCountNames;
    public ArrayList<Integer> countIds;
    public ArrayList<CountEditWidget> savedCounts;

    private Bitmap bMap;
    private BitmapDrawable bg;

    //added for duplicates check
    private boolean dupPref;
    String new_count_name = "";
    String oldname;

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

        setContentView(R.layout.activity_edit_section);

        countNames = new ArrayList<>();
        countCodes = new ArrayList<>();
        countIds = new ArrayList<>();
        savedCounts = new ArrayList<>();

        notes_area = (LinearLayout) findViewById(R.id.editingNotesLayout);
        counts_area = (LinearLayout) findViewById(R.id.editingCountsLayout);

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

        /*
         * Restore any edit widgets the user has added previously
         */
        if (savedInstanceState != null) {
            if (savedInstanceState.getSerializable("savedCounts") != null) {
                savedCounts = (ArrayList<CountEditWidget>) savedInstanceState.getSerializable("savedCounts");
            }
        }

        // Load preferences
        transektCount = (TransektCountApplication) getApplication();
        prefs = TransektCountApplication.getPrefs();
        prefs.registerOnSharedPreferenceChangeListener(this);

        boolean brightPref = prefs.getBoolean("pref_bright", true);
        dupPref = prefs.getBoolean("pref_duplicate", 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.editingScreen);
        bMap = transektCount.decodeBitmap(R.drawable.kbackground, transektCount.width, transektCount.height);
        bg = new BitmapDrawable(counting_screen.getResources(), bMap);
        counting_screen.setBackground(bg);
    }

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

        // build the Edit Section screen
        // clear any existing views
        counts_area.removeAllViews();
        notes_area.removeAllViews();

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

        // load the sections data
        section = sectionDataSource.getSection(section_id);
        oldname = section.name;
        try {
            getSupportActionBar().setTitle(oldname);
        } catch (NullPointerException e) {
            Log.i(TAG, "NullPointerException: No section name!");
        }

        // display the section title
        etw = new EditTitleWidget(this, null);
        etw.setSectionName(oldname);
        etw.setWidgetTitle(getString(R.string.titleEdit));
        notes_area.addView(etw);

        // display editable section notes; the same class
        // is being used for both due to being lazy
        enw = new EditNotesWidget(this, null);
        enw.setSectionNotes(section.notes);
        enw.setWidgetNotes(getString(R.string.notesHere));
        enw.setHint(getString(R.string.notesHint));
        enw.requestFocus();
        notes_area.addView(enw);

        // load the counts data
        counts = countDataSource.getAllCountsForSection(section.id);

        // display all the counts by adding them to countCountLayout
        for (Count count : counts) {
            // widget
            CountEditWidget cew = new CountEditWidget(this, null);
            cew.setCountName(count.name);
            cew.setCountCode(count.code);
            cew.setCountId(count.id);
            counts_area.addView(cew);
        }
        for (CountEditWidget cew : savedCounts) {
            counts_area.addView(cew);
        }
        getCountNames();
    }

    @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 (CountEditWidget cew : savedCounts) {
            ((ViewGroup) cew.getParent()).removeView(cew);
        }
        outState.putSerializable("savedCounts", savedCounts);
    }

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

        // close the data sources
        sectionDataSource.close();
        countDataSource.close();
        alertDataSource.close();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.edit_section, 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) {
            if (saveData()) {
                savedCounts.clear();
                super.finish();
            }
        } else if (id == R.id.newCount) {
            newCount(findViewById(R.id.editingCountsLayout));
        }
        return super.onOptionsItemSelected(item);
    }

    public void getCountNames() {
        /*
         * The plan here is that names, codes and ids arrays contain the entries in the same
         * order, so I can link count and code name to its id by knowing the index.
         */
        countNames.clear();
        countCodes.clear();
        countIds.clear();
        int childcount = counts_area.getChildCount();
        for (int i = 0; i < childcount; i++) {
            CountEditWidget cew = (CountEditWidget) counts_area.getChildAt(i);
            String name = cew.getCountName();
            String code = cew.getCountCode();
            // ignore count widgets where the user has filled nothing in. 
            // Id will be 0 if this is a new count.
            if (isNotEmpty(name)) {
                countNames.add(name);
                countCodes.add(code);
                countIds.add(cew.countId);
            }
        }
    }

    // Compare count names for duplicates and returns name of 1. duplicate found
    public String compCountNames() {
        String name = "";
        String isDbl = "";
        cmpCountNames = new ArrayList<String>();

        int childcount = counts_area.getChildCount();
        // for all CountEditWidgets
        for (int i = 0; i < childcount; i++) {
            CountEditWidget cew = (CountEditWidget) counts_area.getChildAt(i);
            name = cew.getCountName();

            if (cmpCountNames.contains(name)) {
                isDbl = name;
                //Log.i(TAG, "Double name = " + isDbl);
                break;
            }
            cmpCountNames.add(name);
        }
        return isDbl;
    }

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

    public boolean saveData() {
        // save section notes only if they have changed
        boolean savesection = false;

        String newtitle = etw.getSectionName();

        if (isNotEmpty(newtitle)) {
            //check if this is not a duplicate of an existing name
            if (compSectionNames(newtitle)) {
                Toast.makeText(EditSectionActivity.this, newtitle + " " + getString(R.string.isdouble),
                        Toast.LENGTH_SHORT).show();
                savesection = false;
            } else {
                section.name = newtitle;
                savesection = true;
            }
        } else {
            Toast.makeText(EditSectionActivity.this, newtitle + " " + getString(R.string.isempty),
                    Toast.LENGTH_SHORT).show();
            savesection = false;
        }

        // Always add notes if the user has written some...
        String newnotes = enw.getSectionNotes();
        if (isNotEmpty(newnotes) && savesection) {
            section.notes = newnotes;
        }
        //...if they haven't, only save if the current notes have a value
        else {
            if (isNotEmpty(section.notes)) {
                section.notes = newnotes;
            }
        }

        boolean retValue = false;
        if (savesection) {
            sectionDataSource.saveSection(section);

            // save counts (species list)
            String isDbl = "";
            int childcount; //No. of species in list
            childcount = counts_area.getChildCount();
            //Log.i(TAG, "childcount: " + String.valueOf(childcount));

            // check for unique species names
            if (dupPref) {
                isDbl = compCountNames();
                if (isDbl.equals("")) {
                    // do for all species 
                    for (int i = 0; i < childcount; i++) {
                        CountEditWidget cew = (CountEditWidget) counts_area.getChildAt(i);
                        if (isNotEmpty(cew.getCountName())) {
                            //Log.i(TAG, "cew: " + String.valueOf(cew.countId) + ", " + cew.getCountName());
                            // create or save
                            if (cew.countId == 0) {
                                //Log.i(TAG, "Creating!");
                                //returns newCount
                                countDataSource.createCount(section_id, cew.getCountName(), cew.getCountCode());
                            } else {
                                //Log.i(TAG, "Updating!");
                                countDataSource.updateCountName(cew.countId, cew.getCountName(),
                                        cew.getCountCode());
                            }
                            retValue = true;
                        }
                    }
                } else {
                    Toast.makeText(this, isDbl + " " + getString(R.string.isdouble), Toast.LENGTH_SHORT).show();
                    retValue = false;
                }
            }

            if (retValue) {
                Toast.makeText(EditSectionActivity.this, getString(R.string.sectSaving) + " " + section.name + "!",
                        Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, getString(R.string.empty), Toast.LENGTH_SHORT).show();
            }
        }
        return retValue;
    }

    // Compare section names for duplicates and return TRUE when duplicate found
    // created by wmstein on 10.04.2016
    public boolean compSectionNames(String newname) {
        boolean isDbl = false;
        String sname;

        if (newname.equals(oldname)) {
            return false; // name has not changed
        }

        List<Section> sectionList = sectionDataSource.getAllSectionNames();

        int childcount = sectionList.size() + 1;
        // for all Sections
        for (int i = 1; i < childcount; i++) {
            section = sectionDataSource.getSection(i);
            sname = section.name;
            //Log.i(TAG, "sname = " + sname);
            if (newname.equals(sname)) {
                isDbl = true;
                //Log.i(TAG, "Double name = " + sname);
                break;
            }
        }
        return isDbl;
    }

    // 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 1. row
            if (scroll_amount > scrollY) {
                pageend = true;
            }
        }
    }

    // add new CountEditWidget to view
    public void newCount(View view) {
        CountEditWidget cew = new CountEditWidget(this, null);
        counts_area.addView(cew); // adds a child view cew
        // Scroll to end of view, added by wmstein
        View scrollV = findViewById(R.id.editingScreen);
        ScrollToEndOfView(scrollV);
        // set focus to cew, added by wmstein
        cew.requestFocus();
        savedCounts.add(cew);
    }

    // purging counts (with associated alerts)
    public void deleteCount(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.
         */
        markedForDelete = view;
        idToDelete = (Integer) view.getTag();
        if (idToDelete == 0) {
            // the actual CountEditWidget is two levels up from the button in which it is embedded
            counts_area.removeView((CountEditWidget) 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.deleteCount));
            areYouSure.setMessage(getString(R.string.reallyDeleteCount));
            areYouSure.setPositiveButton(R.string.yesDeleteIt, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                    // go ahead for the delete
                    countDataSource.deleteCountById(idToDelete);
                    counts_area.removeView((CountEditWidget) markedForDelete.getParent().getParent());
                    new_count_name = "";
                }
            });
            areYouSure.setNegativeButton(R.string.noCancel, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                    // Cancelled.
                }
            });
            areYouSure.show();
        }
        getCountNames();
    }

    public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
        ScrollView counting_screen = (ScrollView) findViewById(R.id.editingScreen);
        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);

        //added for duplicates check
        dupPref = prefs.getBoolean("duplicate_counts", true);
    }

    /**
     * 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.
     * <p>
     * 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.
     * <p>
     * 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;
    }

}