diff --git a/astrid/common-src/com/todoroo/andlib/widget/NNumberPickerDialog.java b/astrid/common-src/com/todoroo/andlib/widget/NNumberPickerDialog.java deleted file mode 100644 index 4abb73e14..000000000 --- a/astrid/common-src/com/todoroo/andlib/widget/NNumberPickerDialog.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * ASTRID: Android's Simple Task Recording Dashboard - * - * Copyright (c) 2009 Tim Su - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package com.todoroo.andlib.widget; - -import java.util.LinkedList; -import java.util.List; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.FrameLayout.LayoutParams; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.todoroo.andlib.service.Autowired; -import com.todoroo.andlib.service.DependencyInjectionService; - -/** Dialog box with an arbitrary number of number pickers */ -public class NNumberPickerDialog extends AlertDialog implements OnClickListener { - - @Autowired - private Integer nNumberPickerLayout; - - public interface OnNNumberPickedListener { - void onNumbersPicked(int[] number); - } - - private final List pickers = new LinkedList(); - private final OnNNumberPickedListener mCallback; - - /** Instantiate the dialog box. - * - * @param context - * @param callBack callback function to get the numbers you requested - * @param title title of the dialog box - * @param initialValue initial picker values array - * @param incrementBy picker increment by array - * @param start picker range start array - * @param end picker range end array - * @param separators text separating the spinners. whole array, or individual - * elements can be null - */ - public NNumberPickerDialog(Context context, OnNNumberPickedListener callBack, - String title, int[] initialValue, int[] incrementBy, int[] start, - int[] end, String[] separators) { - super(context); - mCallback = callBack; - - DependencyInjectionService.getInstance().inject(this); - - setButton(context.getText(android.R.string.ok), this); - setButton2(context.getText(android.R.string.cancel), (OnClickListener) null); - - LayoutInflater inflater = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View view = inflater.inflate(nNumberPickerLayout, null); - setView(view); - LinearLayout container = (LinearLayout)view; - - setTitle(title); - LayoutParams npLayout = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.FILL_PARENT); - npLayout.gravity = 1; - LayoutParams sepLayout = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.FILL_PARENT); - for(int i = 0; i < incrementBy.length; i++) { - NumberPickerWidget np = new NumberPickerWidget(context, null); - np.setIncrementBy(incrementBy[i]); - np.setLayoutParams(npLayout); - np.setRange(start[i], end[i]); - np.setCurrent(initialValue[i]); - - container.addView(np); - pickers.add(np); - - if(separators != null && separators[i] != null) { - TextView text = new TextView(context); - text.setText(separators[i]); - if(separators[i].length() < 3) - text.setTextSize(48); - else - text.setTextSize(20); - text.setGravity(Gravity.CENTER); - text.setLayoutParams(sepLayout); - container.addView(text); - } - } - } - - public void setInitialValues(int[] values) { - for(int i = 0; i < pickers.size(); i++) - pickers.get(i).setCurrent(values[i]); - } - - public void onClick(DialogInterface dialog, int which) { - if (mCallback != null) { - int[] values = new int[pickers.size()]; - for(int i = 0; i < pickers.size(); i++) { - pickers.get(i).clearFocus(); - values[i] = pickers.get(i).getCurrent(); - } - mCallback.onNumbersPicked(values); - } - } -} diff --git a/astrid/common-src/com/todoroo/andlib/widget/NumberPickerDialog.java b/astrid/common-src/com/todoroo/andlib/widget/NumberPickerDialog.java deleted file mode 100644 index 0dc1ea803..000000000 --- a/astrid/common-src/com/todoroo/andlib/widget/NumberPickerDialog.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * ASTRID: Android's Simple Task Recording Dashboard - * - * Copyright (c) 2009 Tim Su - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package com.todoroo.andlib.widget; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.view.LayoutInflater; -import android.view.View; - -import com.todoroo.andlib.service.Autowired; -import com.todoroo.andlib.service.DependencyInjectionService; - -public class NumberPickerDialog extends AlertDialog implements OnClickListener { - - @Autowired - private Integer numberPickerDialogLayout; - - @Autowired - private Integer numberPickerId; - - public interface OnNumberPickedListener { - void onNumberPicked(NumberPickerWidget view, int number); - } - - private final NumberPickerWidget mPicker; - private final OnNumberPickedListener mCallback; - - public NumberPickerDialog(Context context, OnNumberPickedListener callBack, - String title, int initialValue, int incrementBy, int start, int end) { - super(context); - DependencyInjectionService.getInstance().inject(this); - - mCallback = callBack; - - setButton(context.getText(android.R.string.ok), this); - setButton2(context.getText(android.R.string.cancel), (OnClickListener) null); - - LayoutInflater inflater = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View view = inflater.inflate(numberPickerDialogLayout, null); - setView(view); - - setTitle(title); - mPicker = (NumberPickerWidget) view.findViewById(numberPickerId); - mPicker.setIncrementBy(incrementBy); - mPicker.setRange(start, end); - mPicker.setCurrent(initialValue); - } - - public void setInitialValue(int initialValue) { - mPicker.setCurrent(initialValue); - } - - public void onClick(DialogInterface dialog, int which) { - if (mCallback != null) { - mPicker.clearFocus(); - mCallback.onNumberPicked(mPicker, mPicker.getCurrent()); - } - } -} diff --git a/astrid/common-src/com/todoroo/andlib/widget/NumberPickerWidget.java b/astrid/common-src/com/todoroo/andlib/widget/NumberPickerWidget.java deleted file mode 100644 index 25039a0c9..000000000 --- a/astrid/common-src/com/todoroo/andlib/widget/NumberPickerWidget.java +++ /dev/null @@ -1,460 +0,0 @@ -/* - * ASTRID: Android's Simple Task Recording Dashboard - * - * Copyright (c) 2009 Tim Su - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package com.todoroo.andlib.widget; - -import android.content.Context; -import android.os.Handler; -import android.os.Looper; -import android.text.InputFilter; -import android.text.Spanned; -import android.text.method.NumberKeyListener; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.View.OnFocusChangeListener; -import android.view.View.OnLongClickListener; -import android.view.animation.Animation; -import android.view.animation.TranslateAnimation; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.todoroo.andlib.service.Autowired; -import com.todoroo.andlib.service.DependencyInjectionService; - -public class NumberPickerWidget extends LinearLayout implements OnClickListener, - OnFocusChangeListener, OnLongClickListener { - - @Autowired - private Integer numberPickerLayout; - - @Autowired - private Integer numberPickerIncrementId; - - @Autowired - private Integer numberPickerDecrementId; - - @Autowired - private Integer numberPickerInputId; - - public interface OnChangedListener { - void onChanged(NumberPickerWidget picker, int oldVal, int newVal); - } - - public interface Formatter { - String toString(int value); - } - - /* - * Use a custom NumberPicker formatting callback to use two-digit minutes - * strings like "01". Keeping a static formatter etc. is the most efficient - * way to do this; it avoids creating temporary objects on every call to - * format(). - */ - public static final NumberPickerWidget.Formatter TWO_DIGIT_FORMATTER = new NumberPickerWidget.Formatter() { - final StringBuilder mBuilder = new StringBuilder(); - final java.util.Formatter mFmt = new java.util.Formatter(mBuilder); - final Object[] mArgs = new Object[1]; - - public String toString(int value) { - mArgs[0] = value; - mBuilder.delete(0, mBuilder.length()); - mFmt.format("%02d", mArgs); //$NON-NLS-1$ - return mFmt.toString(); - } - }; - - protected int incrementBy = 1; - public void setIncrementBy(int incrementBy) { - this.incrementBy = incrementBy; - } - - protected final Handler mHandler; - private final Runnable mRunnable = new Runnable() { - public void run() { - if (mIncrement) { - changeCurrent(mCurrent + incrementBy, mSlideUpInAnimation, mSlideUpOutAnimation); - mHandler.postDelayed(this, mSpeed); - } else if (mDecrement) { - changeCurrent(mCurrent - incrementBy, mSlideDownInAnimation, mSlideDownOutAnimation); - mHandler.postDelayed(this, mSpeed); - } - } - }; - - private final LayoutInflater mInflater; - private final TextView mText; - protected final InputFilter mInputFilter; - protected final InputFilter mNumberInputFilter; - - protected final Animation mSlideUpOutAnimation; - protected final Animation mSlideUpInAnimation; - protected final Animation mSlideDownOutAnimation; - protected final Animation mSlideDownInAnimation; - - protected String[] mDisplayedValues; - protected int mStart; - protected int mEnd; - protected int mCurrent; - protected int mPrevious; - private OnChangedListener mListener; - private Formatter mFormatter; - protected long mSpeed = 500; - - protected boolean mIncrement; - protected boolean mDecrement; - - public NumberPickerWidget(Context context) { - this(context, null); - } - - public NumberPickerWidget(Context context, AttributeSet attrs) { - super(context, attrs); - DependencyInjectionService.getInstance().inject(this); - - setOrientation(VERTICAL); - mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mInflater.inflate(numberPickerLayout, this, true); - - mHandler = new Handler(Looper.getMainLooper()); - mInputFilter = new NumberPickerInputFilter(); - mNumberInputFilter = new NumberRangeKeyListener(); - mIncrementButton = (NumberPickerWidgetButton) findViewById(numberPickerIncrementId); - mIncrementButton.setOnClickListener(this); - mIncrementButton.setOnLongClickListener(this); - mIncrementButton.setNumberPicker(this); - mDecrementButton = (NumberPickerWidgetButton) findViewById(numberPickerDecrementId); - mDecrementButton.setOnClickListener(this); - mDecrementButton.setOnLongClickListener(this); - mDecrementButton.setNumberPicker(this); - - mText = (TextView) findViewById(numberPickerInputId); - mText.setOnFocusChangeListener(this); - mText.setFilters(new InputFilter[] { mInputFilter }); - - mSlideUpOutAnimation = new TranslateAnimation( - Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, - Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, -100); - mSlideUpOutAnimation.setDuration(200); - mSlideUpInAnimation = new TranslateAnimation( - Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, - Animation.RELATIVE_TO_SELF, 100, Animation.RELATIVE_TO_SELF, 0); - mSlideUpInAnimation.setDuration(200); - mSlideDownOutAnimation = new TranslateAnimation( - Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, - Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 100); - mSlideDownOutAnimation.setDuration(200); - mSlideDownInAnimation = new TranslateAnimation( - Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, - Animation.RELATIVE_TO_SELF, -100, Animation.RELATIVE_TO_SELF, 0); - mSlideDownInAnimation.setDuration(200); - - if (!isEnabled()) { - setEnabled(false); - } - } - - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - mIncrementButton.setEnabled(enabled); - mDecrementButton.setEnabled(enabled); - mText.setEnabled(enabled); - } - - public void setOnChangeListener(OnChangedListener listener) { - mListener = listener; - } - - public void setFormatter(Formatter formatter) { - mFormatter = formatter; - } - - /** - * Set the range of numbers allowed for the number picker. The current value - * will be automatically set to the start. - * - * @param start - * the start of the range (inclusive) - * @param end - * the end of the range (inclusive) - */ - public void setRange(int start, int end) { - mStart = start; - mEnd = end; - mCurrent = start; - updateView(); - } - - /** - * Set the range of numbers allowed for the number picker. The current value - * will be automatically set to the start. Also provide a mapping for values - * used to display to the user. - * - * @param start - * the start of the range (inclusive) - * @param end - * the end of the range (inclusive) - * @param displayedValues - * the values displayed to the user. - */ - public void setRange(int start, int end, String[] displayedValues) { - mDisplayedValues = displayedValues; - mStart = start; - mEnd = end; - mCurrent = start; - updateView(); - } - - public void setCurrent(int current) { - mCurrent = current; - updateView(); - } - - /** - * The speed (in milliseconds) at which the numbers will scroll when the the - * +/- buttons are longpressed. Default is 300ms. - */ - public void setSpeed(long speed) { - mSpeed = speed; - } - - public void onClick(View v) { - - /* - * The text view may still have focus so clear it's focus which will - * trigger the on focus changed and any typed values to be pulled. - */ - mText.clearFocus(); - - // now perform the increment/decrement - if (numberPickerIncrementId == v.getId()) { - changeCurrent(mCurrent + incrementBy, mSlideUpInAnimation, - mSlideUpOutAnimation); - } else if (numberPickerDecrementId == v.getId()) { - changeCurrent(mCurrent - incrementBy, mSlideDownInAnimation, - mSlideDownOutAnimation); - } - } - - private String formatNumber(int value) { - return (mFormatter != null) ? mFormatter.toString(value) - : String.valueOf(value); - } - - protected void changeCurrent(int current, - @SuppressWarnings("unused") Animation in, - @SuppressWarnings("unused") Animation out) { - - // Wrap around the values if we go past the start or end - if (current > mEnd) { - current = mStart; - } else if (current < mStart) { - current = mEnd; - } - mPrevious = mCurrent; - mCurrent = current; - notifyChange(); - updateView(); - } - - private void notifyChange() { - if (mListener != null) { - mListener.onChanged(this, mPrevious, mCurrent); - } - } - - private void updateView() { - - /* - * If we don't have displayed values then use the current number else - * find the correct value in the displayed values for the current - * number. - */ - if (mDisplayedValues == null) { - mText.setText(formatNumber(mCurrent)); - } else { - mText.setText(mDisplayedValues[mCurrent - mStart]); - } - } - - private void validateCurrentView(CharSequence str) { - int val = getSelectedPos(str.toString()); - if ((val >= mStart) && (val <= mEnd)) { - mPrevious = mCurrent; - mCurrent = val; - notifyChange(); - } - updateView(); - } - - public void onFocusChange(View v, boolean hasFocus) { - - /* - * When focus is lost check that the text field has valid values. - */ - if (!hasFocus && v instanceof TextView) { - String str = String.valueOf(((TextView) v).getText()); - if ("".equals(str)) { //$NON-NLS-1$ - - // Restore to the old value as we don't allow empty values - updateView(); - } else { - - // Check the new value and ensure it's in range - validateCurrentView(str); - } - } - } - - /** - * We start the long click here but rely on the {@link NumberPickerWidgetButton} - * to inform us when the long click has ended. - */ - public boolean onLongClick(View v) { - - /* - * The text view may still have focus so clear it's focus which will - * trigger the on focus changed and any typed values to be pulled. - */ - mText.clearFocus(); - - if (numberPickerIncrementId == v.getId()) { - mIncrement = true; - mHandler.post(mRunnable); - } else if (numberPickerDecrementId == v.getId()) { - mDecrement = true; - mHandler.post(mRunnable); - } - return true; - } - - public void cancelIncrement() { - mIncrement = false; - } - - public void cancelDecrement() { - mDecrement = false; - } - - protected static final char[] DIGIT_CHARACTERS = new char[] { '0', '1', '2', - '3', '4', '5', '6', '7', '8', '9' }; - - private NumberPickerWidgetButton mIncrementButton; - private NumberPickerWidgetButton mDecrementButton; - - class NumberPickerInputFilter implements InputFilter { - public CharSequence filter(CharSequence source, int start, int end, - Spanned dest, int dstart, int dend) { - if (mDisplayedValues == null) { - return mNumberInputFilter.filter(source, start, end, dest, - dstart, dend); - } - CharSequence filtered = String.valueOf(source.subSequence(start, - end)); - String result = String.valueOf(dest.subSequence(0, dstart)) - + filtered + dest.subSequence(dend, dest.length()); - String str = String.valueOf(result).toLowerCase(); - for (String val : mDisplayedValues) { - val = val.toLowerCase(); - if (val.startsWith(str)) { - return filtered; - } - } - return ""; //$NON-NLS-1$ - } - } - - class NumberRangeKeyListener extends NumberKeyListener { - - @Override - protected char[] getAcceptedChars() { - return DIGIT_CHARACTERS; - } - - @Override - public CharSequence filter(CharSequence source, int start, int end, - Spanned dest, int dstart, int dend) { - - CharSequence filtered = super.filter(source, start, end, dest, - dstart, dend); - if (filtered == null) { - filtered = source.subSequence(start, end); - } - - String result = String.valueOf(dest.subSequence(0, dstart)) - + filtered + dest.subSequence(dend, dest.length()); - - if ("".equals(result)) { //$NON-NLS-1$ - return result; - } - int val = getSelectedPos(result); - - /* - * Ensure the user can't type in a value greater than the max - * allowed. We have to allow less than min as the user might want to - * delete some numbers and then type a new number. - */ - if (val > mEnd) { - return ""; //$NON-NLS-1$ - } else { - return filtered; - } - } - - public int getInputType() { - return 0; - } - } - - protected int getSelectedPos(String str) { - if (mDisplayedValues == null) { - return Integer.parseInt(str); - } else { - for (int i = 0; i < mDisplayedValues.length; i++) { - - /* Don't force the user to type in jan when ja will do */ - str = str.toLowerCase(); - if (mDisplayedValues[i].toLowerCase().startsWith(str)) { - return mStart + i; - } - } - - /* - * The user might have typed in a number into the month field i.e. - * 10 instead of OCT so support that too. - */ - try { - return Integer.parseInt(str); - } catch (NumberFormatException e) { - - /* Ignore as if it's not a number we don't care */ - } - } - return mStart; - } - - /** - * @return the current value. - */ - public int getCurrent() { - return mCurrent; - } -} \ No newline at end of file diff --git a/astrid/common-src/com/todoroo/andlib/widget/NumberPickerWidgetButton.java b/astrid/common-src/com/todoroo/andlib/widget/NumberPickerWidgetButton.java deleted file mode 100644 index dea3c9e47..000000000 --- a/astrid/common-src/com/todoroo/andlib/widget/NumberPickerWidgetButton.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * ASTRID: Android's Simple Task Recording Dashboard - * - * Copyright (c) 2009 Tim Su - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package com.todoroo.andlib.widget; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.widget.ImageButton; - -import com.todoroo.andlib.service.Autowired; -import com.todoroo.andlib.service.DependencyInjectionService; - -/** - * This class exists purely to cancel long click events. - */ -public class NumberPickerWidgetButton extends ImageButton { - - private NumberPickerWidget mNumberPicker; - - @Autowired - private Integer numberPickerIncrementId; - - @Autowired - private Integer numberPickerDecrementId; - - public NumberPickerWidgetButton(Context context, AttributeSet attrs, - int defStyle) { - super(context, attrs, defStyle); - DependencyInjectionService.getInstance().inject(this); - } - - public NumberPickerWidgetButton(Context context, AttributeSet attrs) { - super(context, attrs); - DependencyInjectionService.getInstance().inject(this); - } - - public NumberPickerWidgetButton(Context context) { - super(context); - DependencyInjectionService.getInstance().inject(this); - } - - public void setNumberPicker(NumberPickerWidget picker) { - mNumberPicker = picker; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - cancelLongpressIfRequired(event); - return super.onTouchEvent(event); - } - - @Override - public boolean onTrackballEvent(MotionEvent event) { - cancelLongpressIfRequired(event); - return super.onTrackballEvent(event); - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - if ((keyCode == KeyEvent.KEYCODE_DPAD_CENTER) - || (keyCode == KeyEvent.KEYCODE_ENTER)) { - cancelLongpress(); - } - return super.onKeyUp(keyCode, event); - } - - private void cancelLongpressIfRequired(MotionEvent event) { - if ((event.getAction() == MotionEvent.ACTION_CANCEL) - || (event.getAction() == MotionEvent.ACTION_UP)) { - cancelLongpress(); - } - } - - private void cancelLongpress() { - if (numberPickerIncrementId == getId()) { - mNumberPicker.cancelIncrement(); - } else if (numberPickerDecrementId == getId()) { - mNumberPicker.cancelDecrement(); - } - } -} \ No newline at end of file diff --git a/astrid/plugin-src/com/todoroo/astrid/backup/BackupActivity.java b/astrid/plugin-src/com/todoroo/astrid/backup/BackupActivity.java index cc6c7dbcf..d4816b7c0 100644 --- a/astrid/plugin-src/com/todoroo/astrid/backup/BackupActivity.java +++ b/astrid/plugin-src/com/todoroo/astrid/backup/BackupActivity.java @@ -47,7 +47,7 @@ public class BackupActivity extends Activity { }; new FilePickerBuilder(this, getString(R.string.import_file_prompt), - BackupConstants.getExportDirectory(), + BackupConstants.defaultExportDirectory(), listener).show(); } @@ -58,7 +58,7 @@ public class BackupActivity extends Activity { setResult(RESULT_OK); finish(); } - }); + }, null); } } diff --git a/astrid/plugin-src/com/todoroo/astrid/backup/BackupConstants.java b/astrid/plugin-src/com/todoroo/astrid/backup/BackupConstants.java index cb0824795..9cc96591b 100644 --- a/astrid/plugin-src/com/todoroo/astrid/backup/BackupConstants.java +++ b/astrid/plugin-src/com/todoroo/astrid/backup/BackupConstants.java @@ -62,7 +62,7 @@ public class BackupConstants { * @return export directory for tasks, or null if no SD card */ @CheckForNull - public static File getExportDirectory() { + public static File defaultExportDirectory() { String storageState = Environment.getExternalStorageState(); if (storageState.equals(Environment.MEDIA_MOUNTED)) { String path = Environment.getExternalStorageDirectory().getAbsolutePath(); diff --git a/astrid/plugin-src/com/todoroo/astrid/backup/BackupService.java b/astrid/plugin-src/com/todoroo/astrid/backup/BackupService.java index 9d61282d0..c3dfab9c2 100644 --- a/astrid/plugin-src/com/todoroo/astrid/backup/BackupService.java +++ b/astrid/plugin-src/com/todoroo/astrid/backup/BackupService.java @@ -77,7 +77,8 @@ public class BackupService extends Service { Log.e("error-deleting", "Error deleting old backups", e); //$NON-NLS-1$ //$NON-NLS-2$ } - TasksXmlExporter.exportTasks(context, true, null); + TasksXmlExporter.exportTasks(context, true, null, + backupDirectorySetting.getBackupDirectory()); } catch (Exception e) { Log.e("error-backup", "Error starting backups", e); //$NON-NLS-1$ //$NON-NLS-2$ @@ -149,7 +150,7 @@ public class BackupService extends Service { private BackupDirectorySetting backupDirectorySetting = new BackupDirectorySetting() { public File getBackupDirectory() { - return null; //TasksXmlExporter.getExportDirectory(); + return BackupConstants.defaultExportDirectory(); } }; diff --git a/astrid/plugin-src/com/todoroo/astrid/backup/TasksXmlExporter.java b/astrid/plugin-src/com/todoroo/astrid/backup/TasksXmlExporter.java index 8f8ac11c9..8aa556530 100644 --- a/astrid/plugin-src/com/todoroo/astrid/backup/TasksXmlExporter.java +++ b/astrid/plugin-src/com/todoroo/astrid/backup/TasksXmlExporter.java @@ -17,8 +17,8 @@ import android.widget.Toast; import com.timsu.astrid.R; import com.todoroo.andlib.data.AbstractModel; import com.todoroo.andlib.data.Property; -import com.todoroo.andlib.data.Property.PropertyVisitor; import com.todoroo.andlib.data.TodorooCursor; +import com.todoroo.andlib.data.Property.PropertyVisitor; import com.todoroo.andlib.service.ExceptionService; import com.todoroo.andlib.sql.Order; import com.todoroo.andlib.sql.Query; @@ -38,11 +38,15 @@ public class TasksXmlExporter { /** * Import tasks from the given file * - * @param input - * @param runAfterExport + * @param context context + * @param isService if false, displays ui dialogs + * @param runAfterExport runnable to run after exporting + * @param backupDirectoryOverride new backupdirectory, or null to use default */ - public static void exportTasks(Context context, boolean isService, Runnable runAfterExport) { - new TasksXmlExporter(context, isService, runAfterExport); + public static void exportTasks(Context context, boolean isService, + Runnable runAfterExport, File backupDirectoryOverride) { + new TasksXmlExporter(context, isService, runAfterExport, + backupDirectoryOverride); } // --- implementation @@ -58,6 +62,7 @@ public class TasksXmlExporter { private final ProgressDialog progressDialog; private final Handler handler; + private final File backupDirectory; private void setProgress(final int taskNumber, final int total) { handler.post(new Runnable() { @@ -69,9 +74,11 @@ public class TasksXmlExporter { } private TasksXmlExporter(final Context context, final boolean isService, - final Runnable runAfterExport) { + final Runnable runAfterExport, File backupDirectoryOverride) { this.context = context; this.exportCount = 0; + this.backupDirectory = backupDirectoryOverride == null ? + BackupConstants.defaultExportDirectory() : backupDirectoryOverride; handler = new Handler(); progressDialog = new ProgressDialog(context); @@ -91,7 +98,7 @@ public class TasksXmlExporter { @Override public void run() { try { - String output = setupFile(BackupConstants.getExportDirectory(), + String output = setupFile(backupDirectory, isService); int tasks = taskService.countTasks(); diff --git a/astrid/plugin-src/com/todoroo/astrid/reminders/NotificationActivity.java b/astrid/plugin-src/com/todoroo/astrid/reminders/NotificationActivity.java index 99ec09ac4..96aa4cf03 100644 --- a/astrid/plugin-src/com/todoroo/astrid/reminders/NotificationActivity.java +++ b/astrid/plugin-src/com/todoroo/astrid/reminders/NotificationActivity.java @@ -222,7 +222,10 @@ public class NotificationActivity extends TaskListActivity implements OnTimeSetL } public void snoozeTime(long time) { - ReminderService.getInstance().scheduleSnoozeAlarm(taskId, time); + Task task = new Task(); + task.setId(taskId); + task.setValue(Task.REMINDER_SNOOZE, time); + taskService.save(task); finish(); } diff --git a/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java b/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java index de4ea8c0f..5e8386f25 100644 --- a/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java +++ b/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java @@ -136,11 +136,7 @@ public class Notifications extends BroadcastReceiver { // update last reminder time task.setValue(Task.REMINDER_LAST, DateUtilities.now()); - boolean saved = taskDao.saveExisting(task); - - // schedule next notification (unless couldn't save last time) - if(saved) - ReminderService.getInstance().scheduleAlarm(task); + taskDao.saveExisting(task); Context context = ContextManager.getContext(); String title = context.getString(R.string.app_name); diff --git a/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderService.java b/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderService.java index 4d0299d96..01576e665 100644 --- a/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderService.java +++ b/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderService.java @@ -309,22 +309,6 @@ public final class ReminderService { return NO_ALARM; } - /** - * Schedule a snooze alarm for this task - * @param taskId - * @param time - */ - public void scheduleSnoozeAlarm(long taskId, long time) { - if(time < DateUtilities.now()) - return; - Task task = taskDao.fetch(taskId, PROPERTIES); - scheduler.createAlarm(task, time, TYPE_SNOOZE); - - // record snooze time - task.setValue(Task.REMINDER_SNOOZE, time); - taskDao.saveExisting(task); - } - // --- alarm manager alarm creation /** diff --git a/astrid/src/com/todoroo/astrid/dao/TaskDao.java b/astrid/src/com/todoroo/astrid/dao/TaskDao.java index 3ded1f575..de16552ec 100644 --- a/astrid/src/com/todoroo/astrid/dao/TaskDao.java +++ b/astrid/src/com/todoroo/astrid/dao/TaskDao.java @@ -233,7 +233,9 @@ public class TaskDao extends DatabaseDao { afterComplete(task, values); else if(values.containsKey(Task.DUE_DATE.name) || values.containsKey(Task.REMINDER_FLAGS.name) || - values.containsKey(Task.REMINDER_PERIOD.name)) + values.containsKey(Task.REMINDER_PERIOD.name) || + values.containsKey(Task.REMINDER_LAST.name) || + values.containsKey(Task.REMINDER_SNOOZE.name)) ReminderService.getInstance().scheduleAlarm(task); } diff --git a/astrid/src/com/todoroo/astrid/service/AstridDependencyInjector.java b/astrid/src/com/todoroo/astrid/service/AstridDependencyInjector.java index 422acb7ba..9edf87964 100644 --- a/astrid/src/com/todoroo/astrid/service/AstridDependencyInjector.java +++ b/astrid/src/com/todoroo/astrid/service/AstridDependencyInjector.java @@ -3,7 +3,6 @@ */ package com.todoroo.astrid.service; -import com.timsu.astrid.R; import com.todoroo.andlib.service.AbstractDependencyInjector; import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.service.ExceptionService.AndroidLogReporter; @@ -43,15 +42,6 @@ public class AstridDependencyInjector extends AbstractDependencyInjector { // com.todoroo.android.service injectables.put("applicationName", "astrid"); - // com.todoroo.android.utility - injectables.put("nNumberPickerLayout", R.layout.n_number_picker_dialog); - injectables.put("numberPickerLayout", R.layout.number_picker); - injectables.put("numberPickerIncrementId", R.id.increment); - injectables.put("numberPickerDecrementId", R.id.decrement); - injectables.put("numberPickerId", R.id.numberPicker); - injectables.put("numberPickerInputId", R.id.timepicker_input); - injectables.put("numberPickerDialogLayout", R.layout.number_picker_dialog); - // com.todoroo.astrid.dao injectables.put("database", Database.class); injectables.put("taskDao", TaskDao.class); diff --git a/astrid/src/com/todoroo/astrid/service/StartupService.java b/astrid/src/com/todoroo/astrid/service/StartupService.java index d2adac400..1ac954808 100644 --- a/astrid/src/com/todoroo/astrid/service/StartupService.java +++ b/astrid/src/com/todoroo/astrid/service/StartupService.java @@ -158,7 +158,7 @@ public class StartupService { try { if(Preferences.getCurrentVersion() > 135 && !context.getDatabasePath(database.getName()).exists()) { // we didn't have a database! restore latest file - File directory = BackupConstants.getExportDirectory(); + File directory = BackupConstants.defaultExportDirectory(); if(!directory.exists()) return; File[] children = directory.listFiles(); diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 000000000..2823bd67c --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,3 @@ +bin/ +instrumented/ +coverage.em diff --git a/tests/build.properties b/tests/build.properties index a6504854e..5ab28ee04 100644 --- a/tests/build.properties +++ b/tests/build.properties @@ -3,13 +3,16 @@ # This file must be checked in Version Control Systems, as it is # integral to the build system of your project. -# The name of your application package as defined in the manifest. -# Used by the 'uninstall' rule. -#application-package=com.example.myproject +# This file is only used by the Ant script. -# The name of the source folder. -#source-folder=src +# You can use this to override default values such as +# 'source.dir' for the location of your java source folder and +# 'out.dir' for the location of your output folder. -# The name of the output folder. -#out-folder=bin +# You can also use it define how the release builds are signed by declaring +# the following properties: +# 'key.store' for the location of your keystore and +# 'key.alias' for the name of the key to use. +# The password will be asked during the build when you use the 'release' target. +tested.project.dir=../astrid diff --git a/tests/build.xml b/tests/build.xml index 0002b4bbe..7911acec0 100644 --- a/tests/build.xml +++ b/tests/build.xml @@ -1,23 +1,23 @@ - + - + - + - + - - - - - + + + + + + classpathref="android.antlibs" /> + diff --git a/tests/default.properties b/tests/default.properties index 19c96655d..51e933a98 100644 --- a/tests/default.properties +++ b/tests/default.properties @@ -10,4 +10,4 @@ # Indicates whether an apk should be generated for each density. split.density=false # Project target. -target=android-4 +target=android-8 diff --git a/tests/src/com/todoroo/astrid/backup/BackupServiceTests.java b/tests/src/com/todoroo/astrid/backup/BackupServiceTests.java index 91fdba0e1..baa7b1c06 100644 --- a/tests/src/com/todoroo/astrid/backup/BackupServiceTests.java +++ b/tests/src/com/todoroo/astrid/backup/BackupServiceTests.java @@ -8,11 +8,14 @@ import java.util.Date; import com.timsu.astrid.R; import com.todoroo.andlib.test.TodorooTestCase; +import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.astrid.backup.BackupService.BackupDirectorySetting; import com.todoroo.astrid.utility.Preferences; public class BackupServiceTests extends TodorooTestCase { + private static final long BACKUP_WAIT_TIME = 2000L; + File temporaryDirectory = null; BackupDirectorySetting setting = new BackupDirectorySetting() { @@ -66,6 +69,8 @@ public class BackupServiceTests extends TodorooTestCase { service.setBackupDirectorySetting(setting); service.testBackup(getContext()); + AndroidUtilities.sleepDeep(BACKUP_WAIT_TIME); + // assert file created File[] files = temporaryDirectory.listFiles(); assertEquals(1, files.length); @@ -98,6 +103,8 @@ public class BackupServiceTests extends TodorooTestCase { }); service.testBackup(getContext()); + AndroidUtilities.sleepDeep(BACKUP_WAIT_TIME); + // assert no file created File[] files = temporaryDirectory.listFiles(); assertEquals(0, files.length); @@ -141,6 +148,8 @@ public class BackupServiceTests extends TodorooTestCase { service.setBackupDirectorySetting(setting); service.testBackup(getContext()); + AndroidUtilities.sleepDeep(BACKUP_WAIT_TIME); + // assert the oldest file was deleted assertTrue(temporaryDirectory.listFiles().length < 11); assertFalse(files[4].exists()); diff --git a/tests/src/com/todoroo/astrid/reminders/NotificationTests.java b/tests/src/com/todoroo/astrid/reminders/NotificationTests.java index 7dec8c27d..d9e15d8d3 100644 --- a/tests/src/com/todoroo/astrid/reminders/NotificationTests.java +++ b/tests/src/com/todoroo/astrid/reminders/NotificationTests.java @@ -23,6 +23,11 @@ public class NotificationTests extends DatabaseTestCase { boolean value = false; } + @Override + protected void tearDown() throws Exception { + Notifications.setNotificationManager(null); + } + /** test that a normal task gets a notification */ public void testAlarmToNotification() { final Task task = new Task(); diff --git a/tests/src/com/todoroo/astrid/reminders/ReminderServiceTests.java b/tests/src/com/todoroo/astrid/reminders/ReminderServiceTests.java index 74b69fa0c..c8e98aedf 100644 --- a/tests/src/com/todoroo/astrid/reminders/ReminderServiceTests.java +++ b/tests/src/com/todoroo/astrid/reminders/ReminderServiceTests.java @@ -1,5 +1,7 @@ package com.todoroo.astrid.reminders; +import java.util.Date; + import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.astrid.dao.TaskDao; @@ -37,14 +39,23 @@ public class ReminderServiceTests extends DatabaseTestCase { Task task = new Task(); task.setValue(Task.TITLE, "water"); task.setValue(Task.REMINDER_FLAGS, 0); + task.setValue(Task.REMINDER_PERIOD, 0L); taskDao.save(task); service.scheduleAlarm(task); } /** tests with due date */ public void testDueDates() { + service.setScheduler(new AlarmExpected() { + @Override + public void createAlarm(Task task, long time, int type) { + super.createAlarm(task, time, type); + assertEquals((long)task.getValue(Task.DUE_DATE), time); + assertEquals(type, ReminderService.TYPE_DUE); + } + }); + // test due date in the past - service.setScheduler(new NoAlarmExpected()); final Task task = new Task(); task.setValue(Task.TITLE, "water"); task.setValue(Task.DUE_DATE, DateUtilities.now() - DateUtilities.ONE_DAY); @@ -53,14 +64,6 @@ public class ReminderServiceTests extends DatabaseTestCase { // test due date in the future task.setValue(Task.DUE_DATE, DateUtilities.now() + DateUtilities.ONE_DAY); - service.setScheduler(new AlarmExpected() { - @Override - public void createAlarm(Task task, long time, int type) { - super.createAlarm(task, time, type); - assertEquals((long)task.getValue(Task.DUE_DATE), time); - assertEquals(type, ReminderService.TYPE_DUE); - } - }); taskDao.save(task); assertTrue(((AlarmExpected)service.getScheduler()).alarmCreated); } @@ -87,7 +90,15 @@ public class ReminderServiceTests extends DatabaseTestCase { /** tests with overdue */ public void testOverdue() { // test due date in the future - service.setScheduler(new NoAlarmExpected()); + service.setScheduler(new AlarmExpected() { + @Override + public void createAlarm(Task task, long time, int type) { + super.createAlarm(task, time, type); + assertTrue(time > task.getValue(Task.DUE_DATE)); + assertTrue(time < task.getValue(Task.DUE_DATE) + DateUtilities.ONE_DAY); + assertEquals(type, ReminderService.TYPE_OVERDUE); + } + }); final Task task = new Task(); task.setValue(Task.TITLE, "water"); task.setValue(Task.DUE_DATE, DateUtilities.now() + DateUtilities.ONE_DAY); @@ -100,13 +111,27 @@ public class ReminderServiceTests extends DatabaseTestCase { @Override public void createAlarm(Task task, long time, int type) { super.createAlarm(task, time, type); - assertTrue(time > DateUtilities.now()); + assertTrue(time > DateUtilities.now() - 1000L); assertTrue(time < DateUtilities.now() + 2 * DateUtilities.ONE_DAY); assertEquals(type, ReminderService.TYPE_OVERDUE); } }); taskDao.save(task); assertTrue(((AlarmExpected)service.getScheduler()).alarmCreated); + + // test due date in the past, but recently notified + task.setValue(Task.REMINDER_LAST, DateUtilities.now()); + service.setScheduler(new AlarmExpected() { + @Override + public void createAlarm(Task task, long time, int type) { + super.createAlarm(task, time, type); + assertTrue(time > DateUtilities.now() + DateUtilities.ONE_HOUR); + assertTrue(time < DateUtilities.now() + DateUtilities.ONE_DAY); + assertEquals(type, ReminderService.TYPE_OVERDUE); + } + }); + taskDao.save(task); + assertTrue(((AlarmExpected)service.getScheduler()).alarmCreated); } /** tests with multiple */ @@ -149,11 +174,50 @@ public class ReminderServiceTests extends DatabaseTestCase { assertTrue(((AlarmExpected)service.getScheduler()).alarmCreated); } + + /** tests with snooze */ + public void testSnoozeReminders() { + // test due date and snooze in the future + final Task task = new Task(); + task.setValue(Task.TITLE, "spacemen"); + task.setValue(Task.DUE_DATE, DateUtilities.now() + 5000L); + task.setValue(Task.REMINDER_FLAGS, Task.NOTIFY_AT_DEADLINE); + task.setValue(Task.REMINDER_SNOOZE, DateUtilities.now() + DateUtilities.ONE_WEEK); + service.setScheduler(new AlarmExpected() { + @Override + public void createAlarm(Task task, long time, int type) { + super.createAlarm(task, time, type); + assertTrue(time > DateUtilities.now() + DateUtilities.ONE_WEEK - 1000L); + assertTrue(time < DateUtilities.now() + DateUtilities.ONE_WEEK + 1000L); + assertEquals(type, ReminderService.TYPE_SNOOZE); + } + }); + taskDao.save(task); + assertTrue(((AlarmExpected)service.getScheduler()).alarmCreated); + + // snooze in the past + task.setValue(Task.REMINDER_SNOOZE, DateUtilities.now() - DateUtilities.ONE_WEEK); + service.setScheduler(new AlarmExpected() { + @Override + public void createAlarm(Task task, long time, int type) { + super.createAlarm(task, time, type); + assertTrue(time > DateUtilities.now() - 1000L); + assertTrue(time < DateUtilities.now() + 5000L); + assertEquals(type, ReminderService.TYPE_DUE); + } + }); + taskDao.save(task); + assertTrue(((AlarmExpected)service.getScheduler()).alarmCreated); + } + + // --- helper classes public class NoAlarmExpected implements AlarmScheduler { public void createAlarm(Task task, long time, int type) { - fail("created alarm, no alarm expected"); + if(time == 0 || time == Long.MAX_VALUE) + return; + fail("created alarm, no alarm expected (" + type + ": " + new Date(time)); } } diff --git a/tests/src/com/todoroo/astrid/service/AstridDependencyInjectorTests.java b/tests/src/com/todoroo/astrid/service/AstridDependencyInjectorTests.java index d25d89d0b..73e8d08dc 100644 --- a/tests/src/com/todoroo/astrid/service/AstridDependencyInjectorTests.java +++ b/tests/src/com/todoroo/astrid/service/AstridDependencyInjectorTests.java @@ -2,7 +2,6 @@ package com.todoroo.astrid.service; import android.test.AndroidTestCase; -import com.timsu.astrid.R; import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.utility.DialogUtilities; @@ -40,31 +39,15 @@ public class AstridDependencyInjectorTests extends AndroidTestCase { assertTrue(((String)helper.getObject()).length() > 0); } - public void testWithInteger() { - - Helper helper = new Helper() { - @Autowired - public Integer informationDialogTitleResource; - - @Override - public Object getObject() { - return informationDialogTitleResource; - }; - }; - - DependencyInjectionService.getInstance().inject(helper); - assertEquals(R.string.DLG_information_title, helper.getObject()); - } - public void testWithClass() { Helper helper = new Helper() { @Autowired - public DialogUtilities dialogUtilities; + public TaskService taskService; @Override public Object getObject() { - return dialogUtilities; + return taskService; }; }; @@ -73,17 +56,17 @@ public class AstridDependencyInjectorTests extends AndroidTestCase { Helper helper2 = new Helper() { @Autowired - public DialogUtilities dialogUtilities; + public TaskService taskService; @Override public Object getObject() { - return dialogUtilities; + return taskService; }; }; DependencyInjectionService.getInstance().inject(helper2); - assertEquals(helper.getObject(), helper2.getObject()); + assertTrue(helper.getObject() == helper2.getObject()); } }