/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.redgeek.android.eventrend.category;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputFilter;
import android.text.Spanned;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.LinearLayout.LayoutParams;
import net.redgeek.android.eventrend.EvenTrendActivity;
import net.redgeek.android.eventrend.R;
import net.redgeek.android.eventrend.db.CategoryDbTable;
import net.redgeek.android.eventrend.graph.plugins.TimeSeriesInterpolator;
import net.redgeek.android.eventrend.synthetic.Formula;
import net.redgeek.android.eventrend.synthetic.FormulaEditorActivity;
import net.redgeek.android.eventrend.util.ColorPickerDialog;
import net.redgeek.android.eventrend.util.ComboBox;
import net.redgeek.android.eventrend.util.DynamicSpinner;
import java.util.ArrayList;
public class CategoryEditActivity extends EvenTrendActivity {
static final int DELETE_DIALOG_ID = 0;
static final int DIALOG_HELP_GROUP = 1;
static final int DIALOG_HELP_CATEGORY = 2;
static final int DIALOG_HELP_GOAL = 3;
static final int DIALOG_HELP_COLOR = 4;
static final int DIALOG_HELP_AGGREGATE = 5;
static final int DIALOG_HELP_INTERP = 6;
// synthetic config:
static final int DIALOG_HELP_SYNTHETIC = 7;
static final int DIALOG_HELP_FORMULA = 8;
// standard config:
static final int DIALOG_HELP_DEFAULT_VALUE = 9;
static final int DIALOG_HELP_INCREMENT = 10;
static final int DIALOG_HELP_TYPE = 11;
static final int DIALOG_HELP_ZEROFILL = 12;
// UI elements
private LinearLayout mGroupComboLayout;
private LinearLayout mPeriodRow;
private LinearLayout mInterpRow;
private ComboBox mGroupCombo;
private EditText mCategoryText;
private Button mColorButton;
private DynamicSpinner mPeriodSpinner;
private DynamicSpinner mInterpSpinner;
private EditText mGoalText;
private Button mOk;
private Button mDelete;
private CheckBox mSyntheticCheck;
private RadioGroup mTypeRadioGroup;
private RadioButton mTypeRadio;
// synthetic elements:
private TableRow mFormulaRow;
private Button mFormulaEdit;
// standard elements:
private TableRow mDefaultValueRow;
private EditText mDefaultValueText;
private TableRow mIncrementRow;
private EditText mIncrementText;
private TableRow mZeroFillRow;
private CheckBox mZeroFillCheck;
// Private data
private CategoryDbTable.Row mRow;
private String mPeriod;
private String mInterp;
private String mGroupName;
private long mPeriodMs;
private int mRank;
private Paint mPickerPaint;
private String mColorStr;
private Long mRowId;
private int mMaxRank = 1;
private boolean mSave = false;
private Formula mFormula;
// Listeners
private RadioGroup.OnCheckedChangeListener mTypeListener;
private ColorPickerDialog.OnColorChangedListener mColorChangeListener;
private View.OnClickListener mColorButtonListener;
private Spinner.OnItemSelectedListener mInterpolationListener;
private Spinner.OnItemSelectedListener mPeriodListener;
private CompoundButton.OnCheckedChangeListener mSyntheticListener;
private View.OnClickListener mFormulaEditListener;
private View.OnClickListener mOkListener;
private View.OnClickListener mDeleteListener;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
getSavedStateContent(icicle);
setupUI();
populateFields();
updatePaint(mColorStr);
}
private void getSavedStateContent(Bundle icicle) {
if (icicle != null) {
mRowId = icicle.getLong(CategoryDbTable.KEY_ROWID);
if (mRowId < 0)
mRowId = null;
}
if (mRowId == null) {
Bundle extras = getIntent().getExtras();
if (extras != null) {
mRowId = extras.getLong(CategoryDbTable.KEY_ROWID);
}
}
mMaxRank = getDbh().fetchCategoryMaxRank() + 1;
if (mRowId == null)
mRow = new CategoryDbTable.Row();
else
mRow = getDbh().fetchCategory(mRowId);
}
public static class RestrictedNameFilter implements InputFilter {
private String mInvalidRegex;
public RestrictedNameFilter(String invalidRegex) {
mInvalidRegex = invalidRegex;
}
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
String out = "" + source;
out = out.replaceAll(mInvalidRegex, "");
return out.subSequence(0, out.length());
}
};
private void setupUI() {
setContentView(R.layout.category_edit);
setupListeners();
mGroupCombo = new ComboBox(getCtx());
mGroupComboLayout = (LinearLayout) findViewById(R.id.category_edit_group);
mGroupComboLayout.addView(mGroupCombo, new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
Cursor c = getDbh().fetchAllGroups();
c.moveToFirst();
for (int i = 0; i < c.getCount(); i++) {
String group = CategoryDbTable.getGroupName(c);
mGroupCombo.addMenuItem(group);
if (mGroupName != null && mGroupName.equals(group))
mGroupCombo.setSelection(i);
c.moveToNext();
}
c.close();
setHelpDialog(R.id.category_edit_group_view, DIALOG_HELP_GROUP);
mCategoryText = (EditText) findViewById(R.id.category_edit_name);
InputFilter[] FilterArray = new InputFilter[1];
FilterArray[0] = new RestrictedNameFilter("[\"\\\\]");
mCategoryText.setFilters(FilterArray);
setHelpDialog(R.id.category_edit_name_view, DIALOG_HELP_CATEGORY);
mGoalText = (EditText) findViewById(R.id.category_edit_goal);
setHelpDialog(R.id.category_edit_goal_view, DIALOG_HELP_GOAL);
mColorButton = (Button) findViewById(R.id.category_edit_color);
mColorButton.setOnClickListener(mColorButtonListener);
setHelpDialog(R.id.category_edit_color_view, DIALOG_HELP_COLOR);
mInterpSpinner = new DynamicSpinner(getCtx());
mInterpRow = (LinearLayout) findViewById(R.id.category_edit_interp_menu);
mInterpRow.addView(mInterpSpinner, new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
ArrayList<TimeSeriesInterpolator> interpolators = ((EvenTrendActivity) getCtx())
.getInterpolators();
for (int i = 0; i < interpolators.size(); i++) {
String name = interpolators.get(i).getName();
mInterpSpinner.addSpinnerItem(name, new Long(i));
}
mInterpSpinner.setOnItemSelectedListener(mInterpolationListener);
setHelpDialog(R.id.category_edit_interp_view, DIALOG_HELP_INTERP);
mPeriodSpinner = new DynamicSpinner(getCtx());
mPeriodRow = (LinearLayout) findViewById(R.id.category_edit_agg_menu);
mPeriodRow.addView(mPeriodSpinner, new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
for (int i = 0; i < CategoryDbTable.KEY_PERIODS.length; i++) {
mPeriodSpinner
.addSpinnerItem(CategoryDbTable.KEY_PERIODS[i], new Long(i));
}
mPeriodSpinner.setOnItemSelectedListener(mPeriodListener);
setHelpDialog(R.id.category_edit_agg_view, DIALOG_HELP_AGGREGATE);
mOk = (Button) findViewById(R.id.category_edit_ok);
mOk.setOnClickListener(mOkListener);
mDelete = (Button) findViewById(R.id.category_edit_delete);
mDelete.setOnClickListener(mDeleteListener);
if (mRowId == null) {
mDelete.setVisibility(View.INVISIBLE);
}
mTypeRadioGroup = (RadioGroup) findViewById(R.id.category_edit_type);
mTypeRadioGroup.setOnCheckedChangeListener(mTypeListener);
mTypeRadio = (RadioButton) findViewById(mTypeRadioGroup
.getCheckedRadioButtonId());
setHelpDialog(R.id.category_edit_type_view, DIALOG_HELP_TYPE);
mSyntheticCheck = (CheckBox) findViewById(R.id.category_edit_synthetic);
setHelpDialog(R.id.category_edit_synthetic_view, DIALOG_HELP_SYNTHETIC);
mSyntheticCheck.setOnCheckedChangeListener(mSyntheticListener);
mSyntheticCheck.setChecked(false);
// synthetic elements:
mFormulaRow = (TableRow) findViewById(R.id.category_edit_formula_row);
mFormulaEdit = (Button) findViewById(R.id.category_edit_formula);
mFormulaEdit.setOnClickListener(mFormulaEditListener);
setHelpDialog(R.id.category_edit_formula_view, DIALOG_HELP_FORMULA);
// standard elements:
mDefaultValueRow = (TableRow) findViewById(R.id.category_edit_default_value_row);
mDefaultValueText = (EditText) findViewById(R.id.category_edit_default_value);
setHelpDialog(R.id.category_edit_default_value_view,
DIALOG_HELP_DEFAULT_VALUE);
mIncrementRow = (TableRow) findViewById(R.id.category_edit_increment_row);
mIncrementText = (EditText) findViewById(R.id.category_edit_increment);
setHelpDialog(R.id.category_edit_increment_view, DIALOG_HELP_INCREMENT);
mZeroFillRow = (TableRow) findViewById(R.id.category_edit_zerofill_row);
mZeroFillCheck = (CheckBox) findViewById(R.id.category_edit_zerofill);
setHelpDialog(R.id.category_edit_zerofill_view, DIALOG_HELP_ZEROFILL);
setSyntheticView(false);
}
private void setSyntheticView(boolean synthetic) {
if (synthetic == true) {
mFormulaRow.setVisibility(View.VISIBLE);
mDefaultValueRow.setVisibility(View.GONE);
mIncrementRow.setVisibility(View.GONE);
mZeroFillRow.setVisibility(View.GONE);
} else {
mFormulaRow.setVisibility(View.GONE);
mDefaultValueRow.setVisibility(View.VISIBLE);
mIncrementRow.setVisibility(View.VISIBLE);
mZeroFillRow.setVisibility(View.VISIBLE);
}
}
private void setupListeners() {
mTypeListener = new RadioGroup.OnCheckedChangeListener() {
public void onCheckedChanged(RadioGroup group, int checkedId) {
mTypeRadio = (RadioButton) findViewById(checkedId);
if (mTypeRadio.getText().equals(CategoryDbTable.KEY_TYPE_AVERAGE)) {
mZeroFillCheck.setChecked(false);
mZeroFillCheck.setClickable(false);
} else {
if (mPeriodMs == 0) {
mZeroFillCheck.setChecked(false);
mZeroFillCheck.setClickable(false);
} else {
mZeroFillCheck.setClickable(true);
}
}
}
};
mColorChangeListener = new ColorPickerDialog.OnColorChangedListener() {
public void colorChanged(int color) {
mPickerPaint.setColor(color);
mColorButton.setBackgroundColor(color);
mColorStr = String.format("#%02x%02x%02x", Color.red(color), Color
.green(color), Color.blue(color));
}
};
mColorButtonListener = new View.OnClickListener() {
public void onClick(View view) {
ColorPickerDialog d = new ColorPickerDialog(getCtx(),
mColorChangeListener, mPickerPaint.getColor());
d.show();
}
};
mInterpolationListener = new Spinner.OnItemSelectedListener() {
public void onItemSelected(AdapterView parent, View v, int position,
long id) {
if (v != null) {
mInterp = ((TextView) v).getText().toString();
}
return;
}
public void onNothingSelected(AdapterView arg0) {
return;
}
};
mPeriodListener = new Spinner.OnItemSelectedListener() {
public void onItemSelected(AdapterView parent, View v, int position,
long id) {
mPeriod = ((TextView) v).getText().toString();
mPeriodMs = CategoryDbTable.mapPeriodToMs(mPeriod);
if (mPeriodMs == 0) {
mZeroFillCheck.setChecked(false);
mZeroFillCheck.setClickable(false);
} else {
String type = mTypeRadio.getText().toString();
if (type.equals(CategoryDbTable.KEY_TYPE_AVERAGE)) {
mZeroFillCheck.setChecked(false);
mZeroFillCheck.setClickable(false);
} else {
mZeroFillCheck.setClickable(true);
}
}
return;
}
public void onNothingSelected(AdapterView arg0) {
return;
}
};
mSyntheticListener = new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
setSyntheticView(isChecked);
}
};
mFormulaEditListener = new View.OnClickListener() {
public void onClick(View view) {
mSave = true;
saveState();
mSave = false;
Intent i = new Intent(getCtx(), FormulaEditorActivity.class);
i.putExtra(CATEGORY_ID, mRowId);
startActivityForResult(i, FORMULA_EDIT);
}
};
mOkListener = new View.OnClickListener() {
public void onClick(View view) {
mSave = true;
setResult(RESULT_OK);
finish();
}
};
mDeleteListener = new View.OnClickListener() {
public void onClick(View view) {
showDialog(DELETE_DIALOG_ID);
}
};
}
private void updatePaint(String color) {
int colorInt = Color.parseColor(color);
mPickerPaint = new Paint();
mPickerPaint.setAntiAlias(true);
mPickerPaint.setDither(true);
mPickerPaint.setColor(colorInt);
mPickerPaint.setStyle(Paint.Style.FILL);
mColorButton.setBackgroundColor(colorInt);
}
private void populateFields() {
if (mRowId != null) {
if (mRow == null)
mRow = getDbh().fetchCategory(mRowId);
mGroupCombo.setText(mRow.getGroupName());
mCategoryText.setText(mRow.getCategoryName());
mDefaultValueText.setText(Float.valueOf(mRow.getDefaultValue())
.toString());
mIncrementText.setText(Float.valueOf(mRow.getIncrement()).toString());
mGoalText.setText(Float.valueOf(mRow.getGoal()).toString());
mColorStr = mRow.getColor();
mGroupName = mRow.getGroupName();
mZeroFillCheck.setChecked(mRow.getZeroFill());
mSyntheticCheck.setChecked(mRow.getSynthetic());
mInterp = mRow.getInterpolation();
mRank = mRow.getRank();
mPeriodMs = mRow.getPeriodMs();
mPeriod = CategoryDbTable.mapMsToPeriod(mPeriodMs);
mPeriodSpinner.setSelection(CategoryDbTable.mapMsToIndex(mPeriodMs));
ArrayList<TimeSeriesInterpolator> interpolators = ((EvenTrendActivity) getCtx())
.getInterpolators();
for (int i = 0; i < interpolators.size(); i++) {
String name = interpolators.get(i).getName();
if (mInterp != null && mInterp.equals(name)) {
mInterpSpinner.setSelection(i);
}
}
String type = mRow.getType();
if (type.equals(CategoryDbTable.KEY_TYPE_AVERAGE)) {
mTypeRadio = (RadioButton) findViewById(R.id.category_edit_type_rating);
mZeroFillCheck.setChecked(false);
mZeroFillCheck.setClickable(false);
} else {
mTypeRadio = (RadioButton) findViewById(R.id.category_edit_type_sum);
mZeroFillCheck.setClickable(true);
}
mTypeRadio.setChecked(true);
} else {
mGroupName = "";
mColorStr = "#cccccc";
mRank = mMaxRank;
mZeroFillCheck.setClickable(true);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
if (mRowId != null)
outState.putLong(CategoryDbTable.KEY_ROWID, mRowId);
else
outState.putLong(CategoryDbTable.KEY_ROWID, -1);
super.onSaveInstanceState(outState);
}
@Override
protected void onPause() {
super.onPause();
saveState();
}
@Override
protected void onResume() {
super.onResume();
populateFields();
}
private void saveState() {
if (mSave == true) {
if (mRow == null)
mRow = new CategoryDbTable.Row();
mRow.setGroupName(mGroupCombo.getText().toString());
mRow.setCategoryName(mCategoryText.getText().toString());
mRow.setDefaultValue(Float
.valueOf(mDefaultValueText.getText().toString()).floatValue());
mRow.setIncrement(Float.valueOf(mIncrementText.getText().toString())
.floatValue());
mRow.setGoal(Float.valueOf(mGoalText.getText().toString()).floatValue());
mRow.setColor(mColorStr);
mRow.setPeriodMs(mPeriodMs);
mRow.setInterpolation(mInterp);
mRow.setZeroFill(mZeroFillCheck.isChecked());
mRow.setSynthetic(mSyntheticCheck.isChecked());
if (null == mTypeRadio) {
mTypeRadio = (RadioButton) findViewById(mTypeRadioGroup
.getCheckedRadioButtonId());
}
mRow.setType(mTypeRadio.getText().toString());
if (mRowId == null) {
mRow.setRank(mMaxRank);
long catId = getDbh().createCategory(mRow);
if (catId > 0) {
mRowId = catId;
}
} else {
mRow.setId(mRowId);
mRow.setRank(mRank);
getDbh().updateCategory(mRow);
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
String formula = null;
if (intent != null)
formula = intent.getStringExtra(FORMULA);
if (formula != null)
mFormula.setFormula(formula);
if (mRowId > 0)
mRow = getDbh().fetchCategory(mRowId);
populateFields();
}
@Override
protected Dialog onCreateDialog(int id) {
String title;
String msg;
switch (id) {
case DELETE_DIALOG_ID:
title = "Delete " + mCategoryText.getText().toString() + "?";
msg = "All associated entries will also be deleted!";
return dialog(title, msg);
case DIALOG_HELP_GROUP:
title = getResources().getString(R.string.cat_group_title);
msg = getResources().getString(R.string.cat_group_desc);
return getDialogUtil().newOkDialog(title, msg + "\n");
case DIALOG_HELP_CATEGORY:
title = getResources().getString(R.string.cat_category_title);
msg = getResources().getString(R.string.cat_category_desc);
return getDialogUtil().newOkDialog(title, msg + "\n");
case DIALOG_HELP_DEFAULT_VALUE:
title = getResources().getString(R.string.cat_default_value_title);
msg = getResources().getString(R.string.cat_default_value_desc);
return getDialogUtil().newOkDialog(title, msg + "\n");
case DIALOG_HELP_INCREMENT:
title = getResources().getString(R.string.cat_increment_title);
msg = getResources().getString(R.string.cat_increment_desc);
return getDialogUtil().newOkDialog(title, msg + "\n");
case DIALOG_HELP_GOAL:
title = getResources().getString(R.string.cat_goal_title);
msg = getResources().getString(R.string.cat_goal_desc);
return getDialogUtil().newOkDialog(title, msg + "\n");
case DIALOG_HELP_COLOR:
title = getResources().getString(R.string.cat_color_title);
msg = getResources().getString(R.string.cat_color_desc);
return getDialogUtil().newOkDialog(title, msg + "\n");
case DIALOG_HELP_TYPE:
title = getResources().getString(R.string.cat_type_title);
msg = getResources().getString(R.string.cat_type_desc);
return getDialogUtil().newOkDialog(title, msg + "\n");
case DIALOG_HELP_AGGREGATE:
title = getResources().getString(R.string.cat_aggregate_title);
msg = getResources().getString(R.string.cat_aggregate_desc);
return getDialogUtil().newOkDialog(title, msg + "\n");
case DIALOG_HELP_INTERP:
title = getResources().getString(R.string.cat_interp_title);
msg = getResources().getString(R.string.cat_interp_desc);
ArrayList<TimeSeriesInterpolator> interpolators = ((EvenTrendActivity) getCtx())
.getInterpolators();
for (int i = 0; i < interpolators.size(); i++) {
int helpId = interpolators.get(i).getHelpResId();
msg += "\n---\n" + getResources().getString(helpId);
}
return getDialogUtil().newOkDialog(title, msg + "\n");
case DIALOG_HELP_ZEROFILL:
title = getResources().getString(R.string.cat_zerofill_title);
msg = getResources().getString(R.string.cat_zerofill_desc);
return getDialogUtil().newOkDialog(title, msg + "\n");
case DIALOG_HELP_SYNTHETIC:
title = getResources().getString(R.string.cat_synthetic_title);
msg = getResources().getString(R.string.cat_synthetic_desc);
return getDialogUtil().newOkDialog(title, msg + "\n");
case DIALOG_HELP_FORMULA:
title = getResources().getString(R.string.cat_formula_title);
msg = getResources().getString(R.string.cat_formula_desc);
return getDialogUtil().newOkDialog(title, msg + "\n");
}
return null;
}
private Dialog dialog(String title, String msg) {
Builder b = new AlertDialog.Builder(getCtx());
b.setTitle(title);
b.setMessage(msg);
b.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
getDbh().deleteCategory(mRowId);
getDbh().deleteCategoryEntries(mRowId);
setResult(RESULT_DELETED);
finish();
}
});
b.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
setResult(RESULT_CANCELED);
}
});
Dialog d = b.create();
return d;
}
private void setHelpDialog(int resId, final int dialog) {
TextView tv = (TextView) findViewById(resId);
tv.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
showDialog(dialog);
}
});
}
}