at.florian_lentsch.expirysync.EditProductActivity.java Source code

Java tutorial

Introduction

Here is the source code for at.florian_lentsch.expirysync.EditProductActivity.java

Source

/*
* This file is part of ExpirySync.
*
* ExpirySync 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.
    
* ExpirySync 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 ExpirySync.  If not, see <http://www.gnu.org/licenses/>
*/

package at.florian_lentsch.expirysync;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import org.joda.time.DateTime;

import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;

import at.florian_lentsch.expirysync.db.DatabaseManager;
import at.florian_lentsch.expirysync.model.Article;
import at.florian_lentsch.expirysync.model.ArticleImage;
import at.florian_lentsch.expirysync.model.ProductEntry;
import at.florian_lentsch.expirysync.net.ServerProxy;
import at.florian_lentsch.expirysync.util.Util;

/**
 * Activity displaying a form to edit a product entry starting the activity
 * requires {@link android.content.Intent} to have an extra with
 * {@link ProductListActivity#EXTRA_PRODUCT_ENTRY_ID} set to the ID of the entry
 * to edit
 * 
 * @author Florian Lentsch <office@florian-lentsch.at>
 * 
 */
public class EditProductActivity extends ProductCrudActivity {
    /**
     * the product entry to edit as passed by the the calling activity
     */
    private ProductEntry curEntry = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.product_form);
        loadPhotoFromSaveInstanceState(savedInstanceState);
        initFormFields();
        setupActionBar();
        setupEditForm();
    }

    /**
     * Set up the {@link android.app.ActionBar}, if the API is available.
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private void setupActionBar() {
        ActionBar actionBar = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && (actionBar = getActionBar()) != null) {
            // TODO: Find out, why this is not being done for android 4 for example:
            actionBar.setDisplayHomeAsUpEnabled(true);
        }
    }

    @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_product, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            NavUtils.navigateUpFromSameTask(this);
            return true;
        case R.id.action_save:
            this.editProduct();
            break;
        case R.id.action_cancel_editing:
            setResult(RESULT_CANCELED);
            finish();
            break;
        case R.id.action_delete:
            this.confirmProductDeletion();
            break;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * fill all the form fields with {@link #curEntry}'s data
     */
    private void setupEditForm() {
        Bundle bundle = getIntent().getExtras();
        int id = bundle.getInt(ProductListActivity.EXTRA_PRODUCT_ENTRY_ID);
        this.curEntry = DatabaseManager.getInstance().getProductEntryById(id);

        Article article = this.curEntry.article;
        ((EditText) findViewById(R.id.barcode_field)).setText(article.barcode);
        ((EditText) findViewById(R.id.product_name_field)).setText(article.name);
        ((EditText) findViewById(R.id.product_description_field)).setText(this.curEntry.description);
        ((EditText) findViewById(R.id.amount_field)).setText(Integer.toString(this.curEntry.amount));
        if (this.photoPath == null) {
            ArticleImage image = this.curEntry.article.getBestImage();
            if (image != null) {
                if (image.imageData != null) {
                    Bitmap bmp = BitmapFactory.decodeByteArray(image.imageData, 0, image.imageData.length);
                    ((ImageView) findViewById(R.id.product_img)).setImageBitmap(bmp);
                } else {
                    // there is an image, but don't have its data in the local db
                    // -> download it from the server:
                    final SharedPreferences sharedPref = this.getApplicationContext().getSharedPreferences("main",
                            Context.MODE_PRIVATE);
                    String hostStr = sharedPref.getString(SettingsActivity.KEY_HOST, "");
                    new DownloadImageTask((ImageView) findViewById(R.id.product_img), image)
                            .execute(hostStr + "article_images/" + image.serverId + "/serve");
                }
            }
        }

        Date expirationDate = this.curEntry.expiration_date;
        Calendar cal = Calendar.getInstance();
        cal.setTime(expirationDate);
        int year = cal.get(Calendar.YEAR), month = cal.get(Calendar.MONTH), day = cal.get(Calendar.DAY_OF_MONTH);
        ((DatePicker) findViewById(R.id.expiration_date_field)).updateDate(year, month, day);
    }

    /**
     * Saves the edit form and then ends the activity
     */
    public void editProduct() {
        // validation:
        if (!this.validateForm()) {
            return;
        }

        // show the loader: 
        Util.showProgress(this);

        // populate db models with form data:
        updateCurrentEntryFromFormData();
        final ArrayList<ArticleImage> imagesList = setFormImageToCurrentEntry();

        this.curEntry.inSync = false;
        ServerProxy entryProxy = ServerProxy.getInstanceFromConfig(this);
        if (entryProxy.getCurrentUser() != null && this.curEntry.serverId > 0) {
            // update the entry on the server:
            entryProxy.updateProductEntry(this.curEntry, imagesList, entryProxy.new ProductEntryCallback() {
                @Override
                public void onReceive(ProductEntry receivedEntry) {
                    EditProductActivity.this.onProductEntryUpdatedOnServer(receivedEntry);
                }
            });
        } else {
            // no user to update the entry with on the server -> exit the activity straight away:
            finishEditing();
        }

        // update the entry in the local db:
        final DatabaseManager dbManager = DatabaseManager.getInstance();
        dbManager.updateProductEntry(this.curEntry);
    }

    /**
     * Updates the entry that is being edited with data entered by the user
     */
    private void updateCurrentEntryFromFormData() {
        final DatabaseManager dbManager = DatabaseManager.getInstance();

        EditText nameField = ((EditText) findViewById(R.id.product_name_field));
        EditText amountField = ((EditText) findViewById(R.id.amount_field));
        String amountStr = amountField.getText().toString();

        this.curEntry.article.barcode = ((EditText) findViewById(R.id.barcode_field)).getText().toString();
        this.curEntry.article.name = nameField.getText().toString();

        this.curEntry.article = dbManager.updateOrAddArticle(this.curEntry.article);

        if (amountStr.trim().equals("")) {
            amountStr = DEFAULT_AMOUNT;
        }
        this.curEntry.amount = Integer.parseInt(amountStr);
        this.curEntry.description = ((EditText) findViewById(R.id.product_description_field)).getText().toString();

        DatePicker datePicker = (DatePicker) findViewById(R.id.expiration_date_field);
        this.curEntry.expiration_date = (new GregorianCalendar(datePicker.getYear(), datePicker.getMonth(),
                datePicker.getDayOfMonth())).getTime();
    }

    /**
     * Adds the image from the form to {@link Article#images} (if there is one)
     * @return list of images (currently only contains 1 or 0
     *         {@link ArticleImage}s)
     */
    private ArrayList<ArticleImage> setFormImageToCurrentEntry() {
        final ArrayList<ArticleImage> imagesList = new ArrayList<ArticleImage>();
        if (this.photoPath == null) {
            return imagesList;
        }

        ArticleImage image = new ArticleImage();
        // TODO: Make image properties configurable:
        image.imageData = getPhotoData(300, 200);
        image.article = this.curEntry.article;
        this.curEntry.article.images.add(image);
        imagesList.add(image);
        return imagesList;
    }

    /**
     * sets the updated entry's serverId in the local db and exits the activity
     * @param receivedEntry entry received from the server
     */
    private void onProductEntryUpdatedOnServer(ProductEntry receivedEntry) {
        if (receivedEntry != null) {
            final DatabaseManager dbManager = DatabaseManager.getInstance();

            this.curEntry.serverId = receivedEntry.serverId;
            this.curEntry.updated_at = receivedEntry.updated_at;
            this.curEntry.inSync = true;
            dbManager.updateProductEntry(this.curEntry);
        } else {
            Util.showMessage(this, "Updating on server failed");
        }

        finishEditing();
    }

    /**
     * Shows a 'really delete this entry'-dialog 
     */
    public void confirmProductDeletion() {
        new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle(R.string.delete_product)
                .setMessage(R.string.really_delete_product)
                .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        EditProductActivity.this.deleteProduct();
                    }
                }).setNegativeButton(R.string.no, null).show();
    }

    /**
     * Deletes {@link #curEntry} from the local db and (if possible) from the server
     */
    private void deleteProduct() {
        final DatabaseManager dbManager = DatabaseManager.getInstance();

        final ServerProxy entryProxy = ServerProxy.getInstanceFromConfig(this);
        if (entryProxy.getCurrentUser() != null && this.curEntry.serverId > 0) {
            entryProxy.deleteProductEntry(this.curEntry, entryProxy.new ProductEntryCallback() {
                @Override
                public void onReceive(ProductEntry receivedEntry) {
                    if (receivedEntry == null) {
                        Util.showMessage(EditProductActivity.this, "Deleting from server failed: ");
                    }
                }
            });
            dbManager.deleteProductEntry(this.curEntry);
        } else {
            this.curEntry.deleted_at = new DateTime();
            this.curEntry.inSync = false;
            dbManager.updateProductEntry(this.curEntry);
        }

        this.curEntry = null;

        finishEditing();
    }

    /**
     * hides the loader, sets the result, and finished the activity
     */
    private void finishEditing() {
        Util.hideProgress();
        setResult(RESULT_OK);
        finish();
    }
}