Lots of changes:
- progress checkboxes - feature: completing a task queries you to stop the timer - feature: 'blocking on' dialog partially complete - feature: notification system... - feature: NNumberPicker - more informative edit screenpull/14/head
@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2008 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.
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- Enabled states -->
|
||||
|
||||
<item android:state_checked="true" android:state_window_focused="false"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_on" />
|
||||
<item android:state_checked="false" android:state_window_focused="false"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_off" />
|
||||
|
||||
<item android:state_checked="true" android:state_pressed="true"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_on_pressed" />
|
||||
<item android:state_checked="false" android:state_pressed="true"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_off_pressed" />
|
||||
|
||||
<item android:state_checked="true" android:state_focused="true"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_on_selected" />
|
||||
<item android:state_checked="false" android:state_focused="true"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_off_selected" />
|
||||
|
||||
<item android:state_checked="false"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_off" />
|
||||
<item android:state_checked="true"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_on" />
|
||||
|
||||
|
||||
<!-- Disabled states -->
|
||||
|
||||
<item android:state_checked="true" android:state_window_focused="false"
|
||||
android:drawable="@drawable/btn_check_on_disable" />
|
||||
<item android:state_checked="false" android:state_window_focused="false"
|
||||
android:drawable="@drawable/btn_check_off_disable" />
|
||||
|
||||
<item android:state_checked="true" android:state_focused="true"
|
||||
android:drawable="@drawable/btn_check_on_disable_focused" />
|
||||
<item android:state_checked="false" android:state_focused="true"
|
||||
android:drawable="@drawable/btn_check_off_disable_focused" />
|
||||
|
||||
<item android:state_checked="false" android:drawable="@drawable/btn_check_off_disable" />
|
||||
<item android:state_checked="true" android:drawable="@drawable/btn_check_on_disable" />
|
||||
|
||||
</selector>
|
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2008 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.
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- Enabled states -->
|
||||
|
||||
<item android:state_checked="true" android:state_pressed="true"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_on_pressed" />
|
||||
<item android:state_checked="false" android:state_pressed="true"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_on_pressed" />
|
||||
|
||||
<item android:state_checked="false"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_25" />
|
||||
<item android:state_checked="true"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_on" />
|
||||
|
||||
</selector>
|
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2008 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.
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- Enabled states -->
|
||||
|
||||
<item android:state_checked="true" android:state_pressed="true"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_on_pressed" />
|
||||
<item android:state_checked="false" android:state_pressed="true"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_on_pressed" />
|
||||
|
||||
<item android:state_checked="false"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_50" />
|
||||
<item android:state_checked="true"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_on" />
|
||||
|
||||
</selector>
|
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2008 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
|
||||
t
|
||||
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.
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- Enabled states -->
|
||||
|
||||
<item android:state_checked="true" android:state_pressed="true"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_on_pressed" />
|
||||
<item android:state_checked="false" android:state_pressed="true"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_on_pressed" />
|
||||
|
||||
<item android:state_checked="false"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_75" />
|
||||
<item android:state_checked="true"
|
||||
android:state_enabled="true"
|
||||
android:drawable="@drawable/btn_check_on" />
|
||||
|
||||
</selector>
|
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 203 B After Width: | Height: | Size: 144 B |
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2008 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.
|
||||
-->
|
||||
|
||||
<transition xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/highlight_pressed" />
|
||||
<item android:drawable="@drawable/highlight_longpress" />
|
||||
</transition>
|
||||
|
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
**
|
||||
** Copyright 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.
|
||||
*/
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/container"
|
||||
android:gravity="center"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="5dip">
|
||||
|
||||
</LinearLayout>
|
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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
|
||||
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<TextView android:id="@+id/greeting"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView android:id="@+id/taskname"
|
||||
android:paddingTop="20dip"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<Button android:id="@+id/btn_viewtask"
|
||||
android:paddingTop="40dip"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/addtask_label"/>
|
||||
|
||||
<Button android:id="@+id/btn_tasklist"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/addtask_label"/>
|
||||
</LinearLayout>
|
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<!-- Choices for the "Reminder minutes" spinner.
|
||||
These must be kept in sync with the reminder_minutes_values array.
|
||||
-->
|
||||
<string-array name="reminders">
|
||||
<item>Hi there! Have a second?</item>
|
||||
<item>Can I see you for a moment?</item>
|
||||
<item>Have a few minutes?</item>
|
||||
<item>I think you forgot to do something...</item>
|
||||
<item>Excuse me?</item>
|
||||
<item>When you have a minute...</item>
|
||||
<item>Look what I dug up!</item>
|
||||
<item>You look energetic today!</item>
|
||||
<item>Here's what I got for you...</item>
|
||||
<item>Are you free for a moment?</item>
|
||||
<item>Your friendly neighborhood assistant here!</item>
|
||||
<item>I would like a minute of your time.</item>
|
||||
<item>It's a beautiful day today, isn't it?</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Astrid says... (user should answer yes or no)-->
|
||||
<string-array name="reminder_responses">
|
||||
<item>I've got something for you!</item>
|
||||
<item>Say hello to my little friend!</item>
|
||||
<item>Why don't you get this done?</item>
|
||||
<item>How about it? Ready tiger?</item>
|
||||
<item>Ready to do this?</item>
|
||||
<item>Can you handle this?</item>
|
||||
<item>You can be happy! Just finish this!</item>
|
||||
<item>Feel the rush of productivity!</item>
|
||||
<item>Won't you do this today?</item>
|
||||
<item>Please finish this, I'm sick of it!</item>
|
||||
<item>Can you finish this? Yes you can!</item>
|
||||
<item>Feel good about yourself! Let's go!</item>
|
||||
<item>I'm so proud of you! Lets get it done!</item>
|
||||
<item>A little snack after you finish this?</item>
|
||||
<item>Just this one task? Please?</item>
|
||||
<item>Time to shorten your todo list!</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* ASTRID: Android's Simple Task Recording Dashboard
|
||||
*
|
||||
* 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.timsu.astrid.activities;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.Resources;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.View.OnCreateContextMenuListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
|
||||
import com.timsu.astrid.R;
|
||||
import com.timsu.astrid.data.tag.TagController;
|
||||
import com.timsu.astrid.data.tag.TagIdentifier;
|
||||
import com.timsu.astrid.data.tag.TagModelForView;
|
||||
import com.timsu.astrid.data.task.TaskController;
|
||||
import com.timsu.astrid.data.task.TaskModelForList;
|
||||
import com.timsu.astrid.utilities.DateUtilities;
|
||||
|
||||
/** Adapter for displaying a list of TaskModelForList entities
|
||||
*
|
||||
* @author timsu
|
||||
*
|
||||
*/
|
||||
public class TaskListAdapter extends ArrayAdapter<TaskModelForList> {
|
||||
|
||||
public static final int CONTEXT_EDIT_ID = Menu.FIRST + 50;
|
||||
public static final int CONTEXT_DELETE_ID = Menu.FIRST + 51;
|
||||
public static final int CONTEXT_TIMER_ID = Menu.FIRST + 52;
|
||||
|
||||
private final Activity activity;
|
||||
private List<TaskModelForList> objects;
|
||||
private int resource;
|
||||
private LayoutInflater inflater;
|
||||
private TaskListAdapterHooks hooks;
|
||||
|
||||
public interface TaskListAdapterHooks {
|
||||
List<TaskModelForList> getTaskArray();
|
||||
Map<TagIdentifier, TagModelForView> getTagMap();
|
||||
TaskController getTaskController();
|
||||
TagController getTagController();
|
||||
void performItemClick(View v, int position);
|
||||
}
|
||||
|
||||
public TaskListAdapter(Activity activity, Context context, int resource,
|
||||
List<TaskModelForList> objects, TaskListAdapterHooks hooks) {
|
||||
super(context, resource, objects);
|
||||
|
||||
inflater = (LayoutInflater)context.getSystemService(
|
||||
Context.LAYOUT_INFLATER_SERVICE);
|
||||
this.objects = objects;
|
||||
this.resource = resource;
|
||||
this.activity = activity;
|
||||
this.hooks = hooks;
|
||||
}
|
||||
|
||||
// --- code for setting up each view
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view;
|
||||
|
||||
view = inflater.inflate(resource, parent, false);
|
||||
setupView(view, objects.get(position));
|
||||
addListeners(position, view);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void setupView(View view, final TaskModelForList task) {
|
||||
Resources r = activity.getResources();
|
||||
|
||||
// find UI components
|
||||
final TextView name = ((TextView)view.findViewById(R.id.text1));
|
||||
final TextView dueDateView = ((TextView)view.findViewById(R.id.text_dueDate));
|
||||
final TextView tagsView = ((TextView)view.findViewById(R.id.text_tags));
|
||||
final CheckBox progress = ((CheckBox)view.findViewById(R.id.cb1));
|
||||
final ImageView timer = ((ImageView)view.findViewById(R.id.image1));
|
||||
final LinearLayout properties = (LinearLayout)view.findViewById(R.id.prop_layout);
|
||||
|
||||
view.setTag(task);
|
||||
progress.setTag(task);
|
||||
|
||||
name.setText(task.getName());
|
||||
if(task.getTimerStart() != null)
|
||||
timer.setImageDrawable(r.getDrawable(R.drawable.ic_dialog_time));
|
||||
progress.setChecked(task.isTaskCompleted());
|
||||
|
||||
// due date
|
||||
boolean hasProperties = false;
|
||||
Date dueDate = task.getDefiniteDueDate();
|
||||
if(dueDate == null || (task.getPreferredDueDate() != null &&
|
||||
task.getPreferredDueDate().getTime() < dueDate.getTime()))
|
||||
dueDate = task.getPreferredDueDate();
|
||||
if(dueDate != null) {
|
||||
int secondsLeft = (int)(dueDate.getTime() -
|
||||
System.currentTimeMillis()) / 1000;
|
||||
String dueString = " " + DateUtilities.getDurationString(r,
|
||||
Math.abs(secondsLeft), 1);
|
||||
if(secondsLeft > 0)
|
||||
dueString = r.getString(R.string.taskList_dueIn) + dueString;
|
||||
else
|
||||
dueString = r.getString(R.string.taskList_overdueBy) + dueString;
|
||||
dueDateView.setText(dueString);
|
||||
hasProperties = true;
|
||||
} else
|
||||
dueDateView.setVisibility(View.GONE);
|
||||
|
||||
// tags
|
||||
List<TagIdentifier> tags = hooks.getTagController().getTaskTags(
|
||||
activity, task.getTaskIdentifier());
|
||||
StringBuilder tagString = new StringBuilder();
|
||||
for(Iterator<TagIdentifier> i = tags.iterator(); i.hasNext(); ) {
|
||||
TagModelForView tag = hooks.getTagMap().get(i.next());
|
||||
tagString.append(tag.getName());
|
||||
if(i.hasNext())
|
||||
tagString.append(", ");
|
||||
}
|
||||
if(tagString.length() > 0) {
|
||||
tagsView.setText(r.getString(R.string.tags_suffix) + tagString);
|
||||
hasProperties = true;
|
||||
}
|
||||
|
||||
if(!hasProperties) { // no properties, old school view
|
||||
properties.setVisibility(View.GONE);
|
||||
name.setTextSize(36);
|
||||
name.setBackgroundColor(r.getColor(R.color.importance_2));
|
||||
}
|
||||
|
||||
setTaskAppearance(task, name, progress);
|
||||
}
|
||||
|
||||
private void addListeners(final int position, final View view) {
|
||||
final CheckBox progress = ((CheckBox)view.findViewById(R.id.cb1));
|
||||
final TextView name = ((TextView)view.findViewById(R.id.text1));
|
||||
|
||||
// clicking the check box
|
||||
progress.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView,
|
||||
boolean isChecked) {
|
||||
TaskModelForList task = (TaskModelForList)buttonView.getTag();
|
||||
|
||||
int newProgressPercentage;
|
||||
if(isChecked)
|
||||
newProgressPercentage =
|
||||
TaskModelForList.getCompletedPercentage();
|
||||
else
|
||||
newProgressPercentage = 0;
|
||||
|
||||
if(newProgressPercentage != task.getProgressPercentage()) {
|
||||
setTaskProgress(task, view, newProgressPercentage);
|
||||
setTaskAppearance(task, name, progress);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// clicking the text field
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
hooks.performItemClick(view, position);
|
||||
}
|
||||
});
|
||||
|
||||
// long-clicking the text field
|
||||
view.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||
ContextMenuInfo menuInfo) {
|
||||
TaskModelForList task = (TaskModelForList)v.getTag();
|
||||
|
||||
menu.add(position, CONTEXT_EDIT_ID, Menu.NONE,
|
||||
R.string.taskList_context_edit);
|
||||
menu.add(position, CONTEXT_DELETE_ID, Menu.NONE,
|
||||
R.string.taskList_context_delete);
|
||||
|
||||
int timerTitle;
|
||||
if(task.getTimerStart() == null)
|
||||
timerTitle = R.string.taskList_context_startTimer;
|
||||
else
|
||||
timerTitle = R.string.taskList_context_stopTimer;
|
||||
menu.add(position, CONTEXT_TIMER_ID, Menu.NONE, timerTitle);
|
||||
|
||||
menu.setHeaderTitle(task.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setTaskProgress(final TaskModelForList task, View view, int progress) {
|
||||
final ImageView timer = ((ImageView)view.findViewById(R.id.image1));
|
||||
task.setProgressPercentage(progress);
|
||||
hooks.getTaskController().saveTask(task);
|
||||
|
||||
// if our timer is on, ask if we want to stop
|
||||
if(task.getTimerStart() != null) {
|
||||
new AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.question_title)
|
||||
.setMessage(R.string.stop_timer_title)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setPositiveButton(android.R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
task.stopTimerAndUpdateElapsedTime();
|
||||
hooks.getTaskController().saveTask(task);
|
||||
timer.setVisibility(View.GONE);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void setTaskAppearance(TaskModelForList task, TextView name, CheckBox progress) {
|
||||
Resources r = activity.getResources();
|
||||
|
||||
if(task.isTaskCompleted()) {
|
||||
name.setBackgroundDrawable(r.getDrawable(R.drawable.strikeout));
|
||||
name.setTextColor(r.getColor(R.color.task_list_done));
|
||||
} else {
|
||||
name.setBackgroundDrawable(null);
|
||||
name.setTextColor(r.getColor(task.getTaskColorResource()));
|
||||
|
||||
if(task.getProgressPercentage() >= 75)
|
||||
progress.setButtonDrawable(R.drawable.btn_check75);
|
||||
else if(task.getProgressPercentage() >= 50)
|
||||
progress.setButtonDrawable(R.drawable.btn_check50);
|
||||
else if(task.getProgressPercentage() >= 25)
|
||||
progress.setButtonDrawable(R.drawable.btn_check25);
|
||||
else
|
||||
progress.setButtonDrawable(R.drawable.btn_check0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.timsu.astrid.data.task;
|
||||
|
||||
import android.database.Cursor;
|
||||
|
||||
import com.timsu.astrid.data.AbstractController;
|
||||
import com.timsu.astrid.utilities.Notifications.Notifiable;
|
||||
|
||||
|
||||
|
||||
/** Fields that you would want to see in the TaskView activity */
|
||||
public class TaskModelForNotify extends AbstractTaskModel implements Notifiable {
|
||||
|
||||
static String[] FIELD_LIST = new String[] {
|
||||
AbstractController.KEY_ROWID,
|
||||
NOTIFICATIONS,
|
||||
};
|
||||
|
||||
// --- constructors
|
||||
|
||||
public TaskModelForNotify(Cursor cursor) {
|
||||
super(cursor);
|
||||
getNotificationIntervalSeconds();
|
||||
}
|
||||
|
||||
// --- getters and setters
|
||||
|
||||
@Override
|
||||
public Integer getNotificationIntervalSeconds() {
|
||||
return super.getNotificationIntervalSeconds();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.timsu.astrid.data.task;
|
||||
|
||||
public class VisibilityProperty {
|
||||
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
package com.timsu.astrid.utilities;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.util.Log;
|
||||
|
||||
import com.timsu.astrid.R;
|
||||
import com.timsu.astrid.activities.TaskView;
|
||||
import com.timsu.astrid.data.task.TaskController;
|
||||
import com.timsu.astrid.data.task.TaskIdentifier;
|
||||
import com.timsu.astrid.data.task.TaskModelForNotify;
|
||||
|
||||
public class Notifications extends BroadcastReceiver {
|
||||
|
||||
private static final int MIN_INTERVAL_SECONDS = 60;
|
||||
private static Random random = new Random();
|
||||
|
||||
@Override
|
||||
/** Startup intent */
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
NotificationManager nm = (NotificationManager) context.
|
||||
getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
Notification notification = new Notification(
|
||||
android.R.drawable.stat_notify_chat, "started up",
|
||||
System.currentTimeMillis());
|
||||
|
||||
nm.notify(0, notification);
|
||||
|
||||
TaskController controller = new TaskController(context);
|
||||
controller.open();
|
||||
List<TaskModelForNotify> tasks = controller.getTasksWithNotifications();
|
||||
|
||||
for(TaskModelForNotify task : tasks)
|
||||
scheduleNextNotification(context, task);
|
||||
}
|
||||
|
||||
public interface Notifiable {
|
||||
public TaskIdentifier getTaskIdentifier();
|
||||
public Integer getNotificationIntervalSeconds();
|
||||
}
|
||||
|
||||
/** Schedules the next notification for this task */
|
||||
public static void scheduleNextNotification(Context context,
|
||||
Notifiable task) {
|
||||
if(task.getNotificationIntervalSeconds() == null ||
|
||||
task.getNotificationIntervalSeconds() == 0 ||
|
||||
task.getTaskIdentifier() == null)
|
||||
return;
|
||||
|
||||
// TODO if task is hidden, disregard
|
||||
|
||||
// add a fudge factor to mix things up a bit
|
||||
int nextSeconds = (int)((random.nextFloat() * 0.2f + 0.8f) *
|
||||
task.getNotificationIntervalSeconds()/60); // TODO remove /60
|
||||
if(nextSeconds < MIN_INTERVAL_SECONDS)
|
||||
nextSeconds = MIN_INTERVAL_SECONDS;
|
||||
long when = System.currentTimeMillis() + nextSeconds * 1000;
|
||||
scheduleNotification(context, task.getTaskIdentifier(), when);
|
||||
}
|
||||
|
||||
|
||||
/** Clear notifications associated with this application */
|
||||
public static void clearAllNotifications(Context context, TaskIdentifier taskId) {
|
||||
NotificationManager nm = (NotificationManager)
|
||||
context.getSystemService(Activity.NOTIFICATION_SERVICE);
|
||||
nm.cancel((int)taskId.getId());
|
||||
}
|
||||
|
||||
/** Schedule a new notification about the given task */
|
||||
public static void scheduleNotification(Context context,
|
||||
TaskIdentifier taskId, long when) {
|
||||
|
||||
NotificationManager nm = (NotificationManager) context
|
||||
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
Resources r = context.getResources();
|
||||
|
||||
Intent notifyIntent = new Intent(context, TaskView.class);
|
||||
notifyIntent.putExtra(TaskView.LOAD_INSTANCE_TOKEN,
|
||||
taskId.getId());
|
||||
notifyIntent.putExtra(TaskView.FROM_NOTIFICATION_TOKEN, true);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(context,
|
||||
0, notifyIntent, PendingIntent.FLAG_ONE_SHOT);
|
||||
|
||||
// notification text
|
||||
String appName = r.getString(R.string.app_name);
|
||||
String[] reminders = r.getStringArray(R.array.reminders);
|
||||
int next = random.nextInt(reminders.length);
|
||||
String reminder = reminders[next];
|
||||
|
||||
Notification notification = new Notification(
|
||||
android.R.drawable.stat_notify_chat, reminder, when);
|
||||
|
||||
notification.setLatestEventInfo(context,
|
||||
appName,
|
||||
reminder,
|
||||
pendingIntent);
|
||||
|
||||
notification.defaults = Notification.DEFAULT_ALL;
|
||||
notification.vibrate = new long[] { 300, 50, 50, 300, 100, 300, 100,
|
||||
100, 200 };
|
||||
|
||||
Log.w("Notifications", "Logging notification: " + reminder + " for " +
|
||||
(when - System.currentTimeMillis())/1000 + " seconds from now");
|
||||
nm.notify((int)taskId.getId(), notification);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.timsu.astrid.utilities;
|
||||
|
||||
public class VisibilityCalculator {
|
||||
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.timsu.astrid.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.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.FrameLayout.LayoutParams;
|
||||
|
||||
import com.timsu.astrid.R;
|
||||
|
||||
/** Dialog box with an arbitrary number of number pickers */
|
||||
public class NNumberPickerDialog extends AlertDialog implements OnClickListener {
|
||||
|
||||
public interface OnNNumberPickedListener {
|
||||
void onNumbersPicked(int[] number);
|
||||
}
|
||||
|
||||
private final List<NumberPicker> pickers = new LinkedList<NumberPicker>();
|
||||
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;
|
||||
|
||||
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(R.layout.n_number_picker_dialog, 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++) {
|
||||
NumberPicker np = new NumberPicker(context, null);
|
||||
np.setIncrementBy(incrementBy[i]);
|
||||
np.setLayoutParams(npLayout);
|
||||
np.setCurrent(initialValue[i]);
|
||||
np.setRange(start[i], end[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(24);
|
||||
text.setGravity(Gravity.CENTER_VERTICAL);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|