Android Open Source - TipOnDiscount Tip On Discount






From Project

Back to project page TipOnDiscount.

License

The source code is released under:

GNU General Public License

If you think the Android project TipOnDiscount listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

// Copyright 2011-2013 David A. Greenbaum
/*/*from   w ww.  ja  v a 2 s.  c o  m*/
This file is part of Tip On Discount.

Tip On Discount 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.

Tip On Discount 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 Tip On Discount.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.itllp.tipOnDiscount;

import java.math.BigDecimal;
import java.math.RoundingMode;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnFocusChangeListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.AdapterView.OnItemSelectedListener;

import com.itllp.tipOnDiscount.model.DataModel;
import com.itllp.tipOnDiscount.model.DataModelFactory;
import com.itllp.tipOnDiscount.model.DataModelInitializer;
import com.itllp.tipOnDiscount.model.DataModelInitializerFactory;
import com.itllp.tipOnDiscount.model.DataModelObserver;
import com.itllp.tipOnDiscount.model.persistence.DataModelPersister;
import com.itllp.tipOnDiscount.model.persistence.DataModelPersisterFactory;
import com.itllp.tipOnDiscount.model.update.ActualTipAmountUpdate;
import com.itllp.tipOnDiscount.model.update.ActualTipRateUpdate;
import com.itllp.tipOnDiscount.model.update.BillSubtotalUpdate;
import com.itllp.tipOnDiscount.model.update.BillTotalUpdate;
import com.itllp.tipOnDiscount.model.update.BumpsUpdate;
import com.itllp.tipOnDiscount.model.update.DiscountUpdate;
import com.itllp.tipOnDiscount.model.update.PlannedTipRateUpdate;
import com.itllp.tipOnDiscount.model.update.RoundUpToNearestUpdate;
import com.itllp.tipOnDiscount.model.update.ShareDueUpdate;
import com.itllp.tipOnDiscount.model.update.SplitBetweenUpdate;
import com.itllp.tipOnDiscount.model.update.TaxAmountUpdate;
import com.itllp.tipOnDiscount.model.update.TaxRateUpdate;
import com.itllp.tipOnDiscount.model.update.PlannedTipAmountUpdate;
import com.itllp.tipOnDiscount.model.update.TippableAmountUpdate;
import com.itllp.tipOnDiscount.model.update.TotalDueUpdate;
import com.itllp.tipOnDiscount.model.update.Update;
import com.itllp.tipOnDiscount.util.BigDecimalLabelMap;

public class TipOnDiscount extends ActionBarActivity implements DataModelObserver {
  private DataModel dataModel;
  private DataModelPersister dataModelPersister;
  private TextView billTotalEntry;
  private TextView billSubtotalText;
  private TextView bumpsText;
  private TextView discountEntry;
  private TextView tippableText;
  private TextView taxPercentEntry;
  private TextView taxAmountEntry;
  private TextView tipPercentEntry;
  private TextView tipAmountText;
  private TextView splitBetweenEntry;
  private Spinner roundUpToNearestSpinner;
  BigDecimalLabelMap spinnerMap;
  private Button bumpDownButton;
  private Button bumpUpButton;
  private TextView actualTipAmountText;
  private TextView actualTipPercentText;
  private TextView totalDueText;
  private TextView shareDueText;
    public static final String NO_VALUE = "";
  

  // Create an anonymous implementation of OnFocusListener to detect when a view
  // loses focus.  Views are formatted when the focus leaves them.
  private OnFocusChangeListener focusChangeListener = new OnFocusChangeListener() {
    @Override
    public void onFocusChange(View view, boolean hasFocus) {
      if (hasFocus) {
        return;
      }
      if (view == billTotalEntry) {
        updateBillTotalEntry(null);
      }
      if (view == discountEntry) {
        updateDiscountEntry(null);
      }
      if (view == taxPercentEntry) {
            updateTaxPercentEntry(null);
        }
      if (view == taxAmountEntry) {
        updateTaxAmountEntry(null);
      }
      if (view == tipPercentEntry) {
            updateTipPercentEntry(null);
        }
      if (view == splitBetweenEntry) {
            updateSplitBetweenEntry(null);
        }
    }
  };
  
  
  class AmountTextWatcher implements TextWatcher {
    private final TextView textView;
    
    public AmountTextWatcher(TextView textView) {
      this.textView = textView;
    }
    
    public void afterTextChanged(Editable s) {
      String text = textView.getText().toString();
      BigDecimal amount = new BigDecimal(".00");
      try {
        amount = new BigDecimal(text)
          .setScale(2, RoundingMode.HALF_UP);
        } catch (NumberFormatException e) {
          // Invalid numbers use default amount above
        }
        if (textView == discountEntry) {
          dataModel.setDiscount(amount);
        }
      if (textView == billTotalEntry) {
          dataModel.setBillTotal(amount);
        }
      if (textView == taxAmountEntry) {
          dataModel.setTaxAmount(amount);
        }
      
    }
    
    public void beforeTextChanged(CharSequence s, int start, int count,  
        int after) {}
    public void onTextChanged(CharSequence s, int start, int before, 
        int count) {}
  }
  
  
  class NonZeroIntegerTextWatcher implements TextWatcher {
    private final TextView textView;
    
    public NonZeroIntegerTextWatcher(TextView textView) {
      this.textView = textView;
    }
    
    public void afterTextChanged(Editable s) {
      String text = textView.getText().toString();
      int integer = 1;
      try {
        integer = Integer.parseInt(text);
        if (0 == integer) {
          integer = 1;
        }
        } catch (NumberFormatException e) {
          // Invalid numbers use default amount above
        }
        if (textView == splitBetweenEntry) {
          dataModel.setSplitBetween(integer);
        }
    }
    
    public void beforeTextChanged(CharSequence s, int start, int count,  
        int after) {}
    public void onTextChanged(CharSequence s, int start, int before, 
        int count) {}
  }
  
  
  class PercentTextWatcher implements TextWatcher {
    private TextView textView;
    
    public PercentTextWatcher(TextView textView) {
      this.textView = textView;
    }
    
    public void afterTextChanged(Editable s) {
        String text = textView.getText().toString();
      BigDecimal rate = new BigDecimal(".000");
        try {
          rate = new BigDecimal(text)
            .divide(new BigDecimal("100.000"), 
                5, RoundingMode.HALF_UP);
        } catch (NumberFormatException e) {
          // Invalid numbers use default rate above
        }
      if (textView == taxPercentEntry) {
          dataModel.setTaxRate(rate);
        }
      if (textView == tipPercentEntry) {
          dataModel.setPlannedTipRate(rate);
        }
    }
    
    public void beforeTextChanged(CharSequence s, int start, int count,  
        int after) {}
    public void onTextChanged(CharSequence s, int start, int before, 
        int count) {}
  }
  
  
  public class RoundUpToNearestOnItemSelectedListener implements OnItemSelectedListener {
    @Override
    public void onItemSelected(AdapterView<?> parent, View arg1, int pos,
      long id) {
      String key = parent.getItemAtPosition(pos).toString();
      BigDecimal amount = spinnerMap.getValue(key);
      dataModel.setRoundUpToAmount(amount);
    }

    @Override
    public void onNothingSelected(AdapterView<?> arg0) {
      // Do nothing
    }
  }
  
  
  /** Returns the data model.  This function is for testing only.
   * @return 
   * 
   */
  public DataModel getDataModel() {
    return dataModel;
  }
  
  /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Unlock screen for Android JUnit tests
        Window window = getWindow();  
        window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);

        String[] valueStringArray = getResources().getStringArray
            (com.itllp.tipOnDiscount.R.array.round_up_to_nearest_value_array);
        String[] labelArray = getResources().getStringArray
            (com.itllp.tipOnDiscount.R.array.round_up_to_nearest_label_array);
    spinnerMap = new BigDecimalLabelMap(valueStringArray, labelArray);

        dataModel = DataModelFactory.getDataModel();
        dataModelPersister = DataModelPersisterFactory.getDataModelPersister();
        
        setContentView(R.layout.main);

        dataModel.addObserver(this);
        
        billTotalEntry = (TextView)this.findViewById
          (com.itllp.tipOnDiscount.R.id.bill_total_entry);
        billTotalEntry.addTextChangedListener(new AmountTextWatcher
            (billTotalEntry));
        billTotalEntry.setOnFocusChangeListener(focusChangeListener);

        billSubtotalText = (TextView)this.findViewById
          (com.itllp.tipOnDiscount.R.id.bill_subtotal_text);

        discountEntry = (TextView)this.findViewById
        (com.itllp.tipOnDiscount.R.id.discount_entry);
        discountEntry.addTextChangedListener(new AmountTextWatcher
            (discountEntry));
        discountEntry.setOnFocusChangeListener(focusChangeListener);

        tippableText = (TextView)this.findViewById
          (com.itllp.tipOnDiscount.R.id.tippable_amount_text);
        
        taxPercentEntry = (TextView)this.findViewById
      (com.itllp.tipOnDiscount.R.id.tax_percent_entry);
        taxPercentEntry.addTextChangedListener(new PercentTextWatcher
            (taxPercentEntry));
        taxPercentEntry.setOnFocusChangeListener(focusChangeListener);

        taxAmountEntry = (TextView)this.findViewById
      (com.itllp.tipOnDiscount.R.id.tax_amount_entry);
        taxAmountEntry.addTextChangedListener(new AmountTextWatcher
            (taxAmountEntry));
        taxAmountEntry.setOnFocusChangeListener(focusChangeListener);

        tipPercentEntry = (TextView)this.findViewById
      (com.itllp.tipOnDiscount.R.id.planned_tip_percent_entry);
        tipPercentEntry.addTextChangedListener(new PercentTextWatcher
            (tipPercentEntry));
        tipPercentEntry.setOnFocusChangeListener(focusChangeListener);

        tipAmountText = (TextView)this.findViewById
      (com.itllp.tipOnDiscount.R.id.planned_tip_amount_text);
        
        splitBetweenEntry = (TextView)this.findViewById
      (com.itllp.tipOnDiscount.R.id.split_between_entry);
        splitBetweenEntry.addTextChangedListener(new NonZeroIntegerTextWatcher
            (splitBetweenEntry));
        splitBetweenEntry.setOnFocusChangeListener(focusChangeListener);

        roundUpToNearestSpinner = (Spinner)this.findViewById
      (com.itllp.tipOnDiscount.R.id.round_up_to_nearest_spinner);
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
          this, R.array.round_up_to_nearest_label_array, 
          R.layout.spinnertext);
        // Specify the layout to use when the list of choices appears
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        roundUpToNearestSpinner.setAdapter(adapter);
        roundUpToNearestSpinner.setOnItemSelectedListener
          (new RoundUpToNearestOnItemSelectedListener());
        
        bumpDownButton = (Button)this.findViewById
      (com.itllp.tipOnDiscount.R.id.bump_down_button);
        bumpDownButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                dataModel.bumpDown();
            }
        });
        bumpsText = (TextView)this.findViewById
      (com.itllp.tipOnDiscount.R.id.bumps_text);
        bumpUpButton = (Button)this.findViewById
      (com.itllp.tipOnDiscount.R.id.bump_up_button);
        bumpUpButton.setOnClickListener(new View.OnClickListener() {
          public void onClick(View v) {
            dataModel.bumpUp();
          }
        });

        actualTipAmountText = (TextView)this.findViewById
      (com.itllp.tipOnDiscount.R.id.actual_tip_amount_text);
        
        actualTipPercentText = (TextView)this.findViewById
    (com.itllp.tipOnDiscount.R.id.actual_tip_percent_text);
        
        totalDueText = (TextView)this.findViewById
          (com.itllp.tipOnDiscount.R.id.total_due_text);
    
        shareDueText = (TextView)this.findViewById
          (com.itllp.tipOnDiscount.R.id.share_due_text);
    }

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


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle presses on the action bar items
        switch (item.getItemId()) {
            case R.id.action_new:
                openNew();
                return true;
            case R.id.action_set_defaults:
              startSetDefaults();
              return true;
            case R.id.action_help:
              openHelp();
            default:
                return super.onOptionsItemSelected(item);
        }
    }
    
    
    public void openHelp() {
       new AlertDialog.Builder(this)
        .setTitle(R.string.help_title)
        .setMessage(R.string.help_message)
        .setPositiveButton(R.string.help_ok,
            new DialogInterface.OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {}
        }
            )
            .show();
    }
    
    
    public void openNew() {
      reset();

      setFocusToBillTotalClearFieldAndOpenSoftKeyboard();
    }

  private void setFocusToBillTotalClearFieldAndOpenSoftKeyboard() {
    billTotalEntry.requestFocus();
    billTotalEntry.setText("");
    openSoftKeyboardIfApplicable();
  }

  private void openSoftKeyboardIfApplicable() {
    InputMethodManager imm = (InputMethodManager) getSystemService
        (Context.INPUT_METHOD_SERVICE);
    imm.showSoftInput(billTotalEntry, InputMethodManager.SHOW_FORCED);
  }
    
    
    /**
     * Store the current state of the app.
     * onPause() is always called when an Activity is about to be hidden, 
     * or destroyed.
     *
     * @see android.app.Activity#onPause()
     */
    @Override
    public void onPause() {
        super.onPause();
        saveInstanceState(this);
    }


    /**
     * Restores the current state of the app by restoring the data model,
     * then calling the UI update functions to retrieve data model values.
     * onResume() is always called when an Activity is starting, 
     * or after being hidden.
     *
     * Attempts to read the state from a preferences file. If this read fails,
     * assume it was just installed, so do an initialization. 
     * Regardless, change the state of the app to be the previous position.
     *
     * @see android.app.Activity#onResume()
     */
    @Override
    public void onResume() {
        super.onResume();
        restoreInstanceState(this);        
    }
    
    
    /**
     * Processes an update from the data model.
     * Each attribute of the data model has its own data type to identify 
     * which field in the UI needs to be updated.
     * @param updatedModel should always be our data model
     * @param updatedData contains the updated value
     */
  public void update(DataModel updatedModel, Update updatedData) {
    if (updatedModel == this.dataModel) {
      if (updatedData instanceof BillTotalUpdate) {
        updateBillTotalEntry((BillTotalUpdate)updatedData);
      }
      if (updatedData instanceof BillSubtotalUpdate) {
        updateBillSubtotalEntry((BillSubtotalUpdate)updatedData);
      }
      if (updatedData instanceof BumpsUpdate) {
        updateBumpsText((BumpsUpdate)updatedData);
      }
      if (updatedData instanceof PlannedTipRateUpdate) {
        updateTipPercentEntry((PlannedTipRateUpdate)updatedData);
      }
      if (updatedData instanceof PlannedTipAmountUpdate) {
        updateTipAmountEntry((PlannedTipAmountUpdate)updatedData);
      }
      if (updatedData instanceof ActualTipAmountUpdate) {
        updateActualTipAmountText((ActualTipAmountUpdate)updatedData);
      }
      if (updatedData instanceof ActualTipRateUpdate) {
        updateActualTipPercentText((ActualTipRateUpdate)updatedData);
      }
      if (updatedData instanceof DiscountUpdate) {
        updateDiscountEntry((DiscountUpdate)updatedData);
      }
      if (updatedData instanceof TippableAmountUpdate) {
        updateTippableEntry((TippableAmountUpdate)updatedData);
      }
      if (updatedData instanceof TaxAmountUpdate) {
        updateTaxAmountEntry((TaxAmountUpdate)updatedData);
      }
      if (updatedData instanceof TaxRateUpdate) {
        updateTaxPercentEntry((TaxRateUpdate)updatedData);
      }
      if (updatedData instanceof TotalDueUpdate) {
        updateTotalDueText((TotalDueUpdate)updatedData);
      }
      if (updatedData instanceof ShareDueUpdate) {
        updateShareDueText((ShareDueUpdate)updatedData);
      }
      if (updatedData instanceof SplitBetweenUpdate) {
        updateSplitBetweenEntry((SplitBetweenUpdate)updatedData);
      }
      if (updatedData instanceof RoundUpToNearestUpdate) {
        updateRoundUpToNearestEntry((RoundUpToNearestUpdate)updatedData);
      }
    }
  }
  
  
  /** Formats a rate as a percentage.  Trailing zeroes are removed. */
  public static String formatRateToPercent(BigDecimal rate) {
    rate = rate.multiply(new BigDecimal("100"));
    
    /* Drop scale down to remove trailing zeroes.
    Scale will not be allowed to reduce precision--if the scale
    gets too small, an exception is throw and no change happens. */
    for (int scale=3; scale>=0; --scale) {
      try {
        rate = rate.setScale(scale);
      } catch (ArithmeticException x) {
        // No further scaling
      }
    }
    return rate.toPlainString();
  }
  
  
  /**
   * Resets all attributes in the data model to defaults and updates
   * all fields in the UI.
   */
  public void reset() {
    DataModelInitializer initializer = 
        DataModelInitializerFactory.getDataModelInitializer();
    initializer.initialize(dataModel, this);
    this.updateAllFields();
  }
  
  
  
    /**
     * Read the previous state of the app from the preferences file
     * @param context - The Activity's Context
     */
    public void restoreInstanceState(Context context) {
      dataModelPersister.restoreState(dataModel, context);
        updateAllFields();
    }

    
  /**
   * Updates the actual tip percent field with the value given, or if none 
   * was supplied, the value from the data model.  
   * 
   * This field does not accept user input, so focus is not checked.
   * 
   * @param updatedData updated value.  If this is null, gets the value
   * from the data model.
   */
  private void updateActualTipPercentText(ActualTipRateUpdate updatedData) {
    BigDecimal rate;
    if (updatedData != null) {
      rate = updatedData.getRate();
    } else {
      rate = this.dataModel.getActualTipRate();
    }
    actualTipPercentText.setText(formatRateToPercent(rate));
  }
  
  
  /**
   * Updates the actual tip amount field with the value given, or if none was
   * supplied, the value from the data model.  
   * 
   * This field does not accept user input, so focus is not checked.
   * 
   * @param updatedData updated value.  If this is null, gets the value
   * from the data model.
   */
  private void updateActualTipAmountText(ActualTipAmountUpdate updatedData) {
    BigDecimal amount;
    if (updatedData != null) {
      amount = updatedData.getAmount();
    } else {
      amount = this.dataModel.getActualTipAmount();
    }
    actualTipAmountText.setText(amount.toPlainString());
  }
  
  
  /**
   * Updates the values of all UI fields from the data model.
   */
  public void updateAllFields() {
    updateBillTotalEntry(null);
    updateTaxPercentEntry(null);
    updateTaxAmountEntry(null);
    updateBillSubtotalEntry(null);
    updateDiscountEntry(null);
    updateTippableEntry(null);
    updateTipPercentEntry(null);
    updateTipAmountEntry(null);
    updateSplitBetweenEntry(null);
    updateRoundUpToNearestEntry(null);
    updateBumpsText(null);
    updateActualTipAmountText(null);
    updateActualTipPercentText(null);
    updateTotalDueText(null);
    updateShareDueText(null);
  }
  

  /**
   * Updates the bill total amount field with the value given, or if none
   * was supplied, the value from the data model. 
   * 
   * Does not update the field if it has the focus, as the user is still
   * editing it.
   * 
   * @param updatedData updated value.  If this is null, gets the value
   * from the data model.
   */
  private void updateBillTotalEntry(BillTotalUpdate updatedData) {
    if (!billTotalEntry.isFocused() || null == updatedData) {
      BigDecimal newAmount;
      if (updatedData != null) {
        newAmount = updatedData.getAmount();
      } else {
        newAmount = this.dataModel.getBillTotal();
      }
      billTotalEntry.setText(newAmount.toPlainString());
    }
  }


  /**
   * Updates the bill subtotal amount field with the value given, or if none
   * was supplied, the value from the data model. 
   * 
   * This is not a user-editable field, so focus is not checked.
   * 
   * @param updatedData updated value.  If this is null, gets the value
   * from the data model.
   */
  private void updateBillSubtotalEntry(BillSubtotalUpdate updatedData) {
    BigDecimal newAmount;
    if (updatedData != null) {
      newAmount = updatedData.getAmount();
    } else {
      newAmount = this.dataModel.getBillSubtotal();
    }
    billSubtotalText.setText(newAmount.toPlainString());
  }


  /**
   * Updates the bumps field with the value given, or if none was
   * supplied, the value from the data model.  
   * 
   * This field does not accept user input, so focus is not checked.
   * 
   * @param updatedData updated value.  If this is null, gets the value
   * from the data model.
   */
  private void updateBumpsText(BumpsUpdate updatedData) {
    int newBumps;
    if (updatedData != null) {
      newBumps = updatedData.getValue();
    } else {
      newBumps = this.dataModel.getBumps();
    }
    String bumpsValue = String.valueOf(newBumps);
    bumpsText.setText(bumpsValue);
  }


  /** Updates the discount field with the value given, or if none was
   * supplied, the value from the data model. 
   * 
   * Does not update the field if it has the focus, as the user is still
   * editing it.
   * 
   * @param updatedData updated value.  If this is null, gets the value
   * from the data model.
   */
  private void updateDiscountEntry(DiscountUpdate updatedData) {
    if (!discountEntry.isFocused() || null==updatedData) {
      BigDecimal newAmount;
      if (updatedData != null) {
        newAmount = updatedData.getAmount();
      } else {
        newAmount = this.dataModel.getDiscount();
      }
      discountEntry.setText(newAmount.toPlainString());
    }
  }

  
  /** 
   * Updates the tippable amount field with the value given, or if none
   * was supplied, the value from the data model. 
   * 
   * This is not a user-editable field, so focus is not checked.
   * 
   * @param updatedData updated value.  If this is null, gets the value
   * from the data model.
   */
  private void updateTippableEntry(TippableAmountUpdate updatedData) {
    BigDecimal newAmount;
    if (updatedData != null) {
      newAmount = updatedData.getAmount();
    } else {
      newAmount = this.dataModel.getTippableAmount();
    }
    tippableText.setText(newAmount.toPlainString());
  }


  /**
   * Updates the total due field with the value given, or if none was
   * supplied, the value from the data model.  
   * 
   * This field does not accept user input, so focus is not checked.
   * 
   * @param updatedData updated value.  If this is null, gets the value
   * from the data model.
   */
  private void updateTotalDueText(TotalDueUpdate updatedData) {
    BigDecimal newAmount;
    if (updatedData != null) {
      newAmount = updatedData.getAmount();
    } else {
      newAmount = this.dataModel.getTotalDue();
    }
    totalDueText.setText(newAmount.toPlainString());
  }


  /**
   * Updates the share due field with the value given, or if none was
   * supplied, the value from the data model.  
   * 
   * This field does not accept user input, so focus is not checked.
   * 
   * @param updatedData updated value.  If this is null, gets the value
   * from the data model.
   */
  private void updateShareDueText(ShareDueUpdate updatedData) {
    BigDecimal newAmount;
    if (updatedData != null) {
      newAmount = updatedData.getAmount();
    } else {
      newAmount = this.dataModel.getShareDue();
    }
    shareDueText.setText(newAmount.toPlainString());
  }
  
  
  /**
   * Update the tax amount field with the value given, or if none was
   * supplied, the value from the data model. 
   * 
   * Does not update the field if it has the focus, as the user is still
   * editing it.
   * 
   * @param updatedData updated value.  If this is null, gets the value
   * from the data model.
   */
  private void updateTaxAmountEntry(TaxAmountUpdate updatedData) {
    if (!taxAmountEntry.isFocused() || null==updatedData) {
      BigDecimal newAmount;
      if (updatedData != null) {
        newAmount = updatedData.getAmount();
      } else {
        newAmount = this.dataModel.getTaxAmount();
      }
      taxAmountEntry.setText(newAmount.toPlainString());
    }
  }
  
  
  /**
   * Updates the tax percentage field with the value given, or if none was
   * supplied, the value from the data model. 
   * 
   * Does not update the field if it has the focus, as the user is still
   * editing it.
   * 
   * @param updatedData updated value.  If this is null, gets the value
   * from the data model.
   */
  private void updateTaxPercentEntry(TaxRateUpdate updatedData) {
    if (!taxPercentEntry.isFocused() || null == updatedData) {
      BigDecimal newRate;
      if (updatedData != null) {
        newRate = updatedData.getRate();
      } else {
        newRate = this.dataModel.getTaxRate();
      }
      taxPercentEntry.setText(formatRateToPercent(newRate));
    }
  }
  

  /**
   * Updates the value in the Tip percent field.  This field does not
   * get changed by any means other than user input, so there's no
   * update notification.
   */
  private void updateTipPercentEntry(PlannedTipRateUpdate updatedData) {
    if (!tipPercentEntry.isFocused() || null==updatedData) { 
      tipPercentEntry.setText(formatRateToPercent
          (this.dataModel.getPlannedTipRate()));
    }
  }

  
  /**
   * Updates the tip amount field with the value given, or if none was
   * supplied, the value from the data model.  
   * 
   * This field does not accept user input, so focus is not checked.
    * 
   * @param updatedData updated value.  If this is null, gets the value
   * from the data model.
   */
  private void updateTipAmountEntry(PlannedTipAmountUpdate updatedData) {
    BigDecimal amount;
    if (updatedData != null) {
      amount = updatedData.getAmount();
    } else {
      amount = this.dataModel.getPlannedTipAmount();
    }
    tipAmountText.setText(amount.toPlainString());
  }

  
  /**
   * Updates the value in the Split Between field.
   */
  private void updateSplitBetweenEntry(SplitBetweenUpdate updatedData) {
    if (!splitBetweenEntry.isFocused() || null==updatedData) { 
      splitBetweenEntry.setText      
        (String.valueOf(this.dataModel.getSplitBetween()));
    }
  }

  
  /**
   * Updates the value in the Round Up To Nearest spinner.
   */
  private void updateRoundUpToNearestEntry(RoundUpToNearestUpdate update) {
    BigDecimal roundUpToAmount;
    if (null == update) {
      roundUpToAmount = this.dataModel.getRoundUpToAmount();
    } else {
      roundUpToAmount = update.getAmount();
    }
    
    String selection = spinnerMap.getLabel(roundUpToAmount);
        int itemCount = roundUpToNearestSpinner.getCount();
        for (int position=0; position<itemCount; ++position) {
          if (roundUpToNearestSpinner.getItemAtPosition(position)
              .equals(selection)) {
            roundUpToNearestSpinner.setSelection(position);
          }
        }    
  }

  
    /**
     * Writes the app's current state to a properties repository.
     * @param context - The Activity's Context
     *
     */
    public void saveInstanceState(Context context) {
      dataModelPersister.saveState(dataModel, context);
    }

  public void startSetDefaults() {
    Intent intent = new Intent(this, SetDefaultsActivity.class);
    startActivity(intent);
  }

  
}




Java Source Code List

android.content.Context.java
com.itllp.tipOnDiscount.SetDefaultsActivity.java
com.itllp.tipOnDiscount.TipOnDiscountApplication.java
com.itllp.tipOnDiscount.TipOnDiscountApplication.java
com.itllp.tipOnDiscount.TipOnDiscount.java
com.itllp.tipOnDiscount.defaults.DefaultsFactory.java
com.itllp.tipOnDiscount.defaults.DefaultsImpl.java
com.itllp.tipOnDiscount.defaults.Defaults.java
com.itllp.tipOnDiscount.defaults.persistence.DefaultsPersisterFactory.java
com.itllp.tipOnDiscount.defaults.persistence.DefaultsPersister.java
com.itllp.tipOnDiscount.defaults.persistence.impl.DefaultsPersisterImpl.java
com.itllp.tipOnDiscount.model.DataModelFactory.java
com.itllp.tipOnDiscount.model.DataModelInitializerFactory.java
com.itllp.tipOnDiscount.model.DataModelInitializer.java
com.itllp.tipOnDiscount.model.DataModelObservableTests.java
com.itllp.tipOnDiscount.model.DataModelObservable.java
com.itllp.tipOnDiscount.model.DataModelObserver.java
com.itllp.tipOnDiscount.model.DataModel.java
com.itllp.tipOnDiscount.model.impl.DataModelImplNotificationTests.java
com.itllp.tipOnDiscount.model.impl.DataModelImplTests.java
com.itllp.tipOnDiscount.model.impl.DataModelImpl.java
com.itllp.tipOnDiscount.model.impl.DataModelInitializerFromPersistedDefaultsTests.java
com.itllp.tipOnDiscount.model.impl.DataModelInitializerFromPersistedDefaults.java
com.itllp.tipOnDiscount.model.impl.SimpleDataModelInitializerTests.java
com.itllp.tipOnDiscount.model.impl.SimpleDataModelInitializer.java
com.itllp.tipOnDiscount.model.persistence.DataModelPersisterFactory.java
com.itllp.tipOnDiscount.model.persistence.DataModelPersister.java
com.itllp.tipOnDiscount.model.persistence.impl.DataModelPersisterImpl.java
com.itllp.tipOnDiscount.model.update.ActualTipAmountUpdate.java
com.itllp.tipOnDiscount.model.update.ActualTipRateUpdate.java
com.itllp.tipOnDiscount.model.update.BillSubtotalUpdate.java
com.itllp.tipOnDiscount.model.update.BillTotalUpdate.java
com.itllp.tipOnDiscount.model.update.BumpsUpdate.java
com.itllp.tipOnDiscount.model.update.DiscountUpdate.java
com.itllp.tipOnDiscount.model.update.PlannedTipAmountUpdate.java
com.itllp.tipOnDiscount.model.update.PlannedTipRateUpdate.java
com.itllp.tipOnDiscount.model.update.RoundUpToNearestUpdate.java
com.itllp.tipOnDiscount.model.update.ShareDueUpdate.java
com.itllp.tipOnDiscount.model.update.SplitBetweenUpdate.java
com.itllp.tipOnDiscount.model.update.TaxAmountUpdate.java
com.itllp.tipOnDiscount.model.update.TaxRateUpdate.java
com.itllp.tipOnDiscount.model.update.TippableAmountUpdate.java
com.itllp.tipOnDiscount.model.update.TotalDueUpdate.java
com.itllp.tipOnDiscount.model.update.UpdateSetTests.java
com.itllp.tipOnDiscount.model.update.UpdateSet.java
com.itllp.tipOnDiscount.model.update.Update.java
com.itllp.tipOnDiscount.persistence.Persister.java
com.itllp.tipOnDiscount.persistence.impl.PreferencesFilePersister.java
com.itllp.tipOnDiscount.util.BigDecimalLabelMap.java
com.itllp.tipOnDiscount.util.EqualsUtil.java