mirror of https://github.com/tasks/tasks
Convert TaskEditControlSets to fragments
parent
5f352a4966
commit
52f7743a46
@ -1,266 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2012 Todoroo Inc
|
|
||||||
*
|
|
||||||
* See the file "LICENSE" for the full license governing this code.
|
|
||||||
*/
|
|
||||||
package com.todoroo.astrid.gcal;
|
|
||||||
|
|
||||||
import android.app.FragmentManager;
|
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.todoroo.astrid.activity.TaskEditFragment;
|
|
||||||
import com.todoroo.astrid.data.Task;
|
|
||||||
import com.todoroo.astrid.helper.TaskEditControlSetBase;
|
|
||||||
|
|
||||||
import org.tasks.R;
|
|
||||||
import org.tasks.activities.CalendarSelectionDialog;
|
|
||||||
import org.tasks.preferences.PermissionRequestor;
|
|
||||||
import org.tasks.preferences.Preferences;
|
|
||||||
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Control Set for managing repeats
|
|
||||||
*
|
|
||||||
* @author Tim Su <tim@todoroo.com>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class GCalControlSet extends TaskEditControlSetBase implements CalendarSelectionDialog.CalendarSelectionHandler {
|
|
||||||
|
|
||||||
private static final String FRAG_TAG_CALENDAR_SELECTION = "frag_tag_calendar_selection";
|
|
||||||
|
|
||||||
// --- instance variables
|
|
||||||
|
|
||||||
private final GCalHelper gcal;
|
|
||||||
private Preferences preferences;
|
|
||||||
private final TaskEditFragment taskEditFragment;
|
|
||||||
private PermissionRequestor permissionRequestor;
|
|
||||||
|
|
||||||
private Uri calendarUri = null;
|
|
||||||
|
|
||||||
private boolean hasEvent = false;
|
|
||||||
private TextView calendar;
|
|
||||||
private ImageView cancelButton;
|
|
||||||
private String calendarId;
|
|
||||||
private String calendarName;
|
|
||||||
|
|
||||||
public GCalControlSet(GCalHelper gcal, Preferences preferences,
|
|
||||||
TaskEditFragment taskEditFragment, PermissionRequestor permissionRequestor) {
|
|
||||||
super(taskEditFragment.getActivity(), R.layout.control_set_gcal_display);
|
|
||||||
this.gcal = gcal;
|
|
||||||
this.preferences = preferences;
|
|
||||||
this.taskEditFragment = taskEditFragment;
|
|
||||||
this.permissionRequestor = permissionRequestor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void afterInflate() {
|
|
||||||
View view = getView();
|
|
||||||
calendar = (TextView) view.findViewById(R.id.calendar_display_which);
|
|
||||||
cancelButton = (ImageView) view.findViewById(R.id.clear);
|
|
||||||
calendar.setOnClickListener(new OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (hasEvent) {
|
|
||||||
viewCalendarEvent();
|
|
||||||
} else {
|
|
||||||
// TODO: show calendar selection if permission has just been granted
|
|
||||||
// can't do this now because the app saves state when TEA is paused,
|
|
||||||
// which triggers calendar creation if there is a default add to calendar.
|
|
||||||
if (permissionRequestor.requestCalendarPermissions()) {
|
|
||||||
showCalendarSelectionDialog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
cancelButton.setOnClickListener(new OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
clearEvent();
|
|
||||||
refreshDisplayView();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showCalendarSelectionDialog() {
|
|
||||||
FragmentManager fragmentManager = taskEditFragment.getFragmentManager();
|
|
||||||
CalendarSelectionDialog fragmentByTag = (CalendarSelectionDialog) fragmentManager.findFragmentByTag(FRAG_TAG_CALENDAR_SELECTION);
|
|
||||||
if (fragmentByTag == null) {
|
|
||||||
fragmentByTag = new CalendarSelectionDialog();
|
|
||||||
fragmentByTag.show(fragmentManager, FRAG_TAG_CALENDAR_SELECTION);
|
|
||||||
}
|
|
||||||
fragmentByTag.setCalendarSelectionHandler(GCalControlSet.this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void readFromTaskOnInitialize() {
|
|
||||||
String uri = gcal.getTaskEventUri(model);
|
|
||||||
if(!TextUtils.isEmpty(uri)) {
|
|
||||||
try {
|
|
||||||
calendarUri = Uri.parse(uri);
|
|
||||||
|
|
||||||
// try to load calendar
|
|
||||||
ContentResolver cr = activity.getContentResolver();
|
|
||||||
Cursor cursor = cr.query(calendarUri, new String[] { "dtstart" }, null, null, null); //$NON-NLS-1$
|
|
||||||
try {
|
|
||||||
boolean deleted = cursor.getCount() == 0;
|
|
||||||
|
|
||||||
if(deleted) {
|
|
||||||
clearEvent();
|
|
||||||
hasEvent = false;
|
|
||||||
} else {
|
|
||||||
hasEvent = true;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Timber.e(e, "unable-to-parse-calendar: %s", model.getCalendarURI());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
hasEvent = false;
|
|
||||||
clearEvent();
|
|
||||||
}
|
|
||||||
refreshDisplayView();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearEvent() {
|
|
||||||
calendarId = null;
|
|
||||||
calendarUri = null;
|
|
||||||
calendarName = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void writeToModelAfterInitialized(Task task) {
|
|
||||||
if (!task.hasDueDate()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((preferences.isDefaultCalendarSet() || calendarId != null) && calendarUri == null) {
|
|
||||||
try{
|
|
||||||
ContentResolver cr = activity.getContentResolver();
|
|
||||||
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
values.put("calendar_id", calendarId);
|
|
||||||
calendarUri = gcal.createTaskEvent(task, cr, values);
|
|
||||||
if(calendarUri != null) {
|
|
||||||
task.setCalendarUri(calendarUri.toString());
|
|
||||||
|
|
||||||
if (!hasEvent) {
|
|
||||||
// pop up the new event
|
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, calendarUri);
|
|
||||||
intent.putExtra("beginTime", values.getAsLong("dtstart"));
|
|
||||||
intent.putExtra("endTime", values.getAsLong("dtend"));
|
|
||||||
activity.startActivity(intent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
Timber.e(e, e.getMessage());
|
|
||||||
}
|
|
||||||
} else if(calendarUri != null) {
|
|
||||||
try {
|
|
||||||
ContentValues updateValues = new ContentValues();
|
|
||||||
|
|
||||||
// check if we need to update the item
|
|
||||||
ContentValues setValues = task.getSetValues();
|
|
||||||
if(setValues.containsKey(Task.TITLE.name)) {
|
|
||||||
updateValues.put("title", task.getTitle());
|
|
||||||
}
|
|
||||||
if(setValues.containsKey(Task.NOTES.name)) {
|
|
||||||
updateValues.put("description", task.getNotes());
|
|
||||||
}
|
|
||||||
if(setValues.containsKey(Task.DUE_DATE.name) || setValues.containsKey(Task.ESTIMATED_SECONDS.name)) {
|
|
||||||
gcal.createStartAndEndDate(task, updateValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
ContentResolver cr = activity.getContentResolver();
|
|
||||||
cr.update(calendarUri, updateValues, null, null);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Timber.e(e, "unable-to-update-calendar: %s", task.getCalendarURI());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void viewCalendarEvent() {
|
|
||||||
if(calendarUri == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ContentResolver cr = activity.getContentResolver();
|
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, calendarUri);
|
|
||||||
Cursor cursor = cr.query(calendarUri, new String[] { "dtstart", "dtend" },
|
|
||||||
null, null, null);
|
|
||||||
try {
|
|
||||||
if(cursor.getCount() == 0) {
|
|
||||||
// event no longer exists, recreate it
|
|
||||||
calendarUri = null;
|
|
||||||
writeToModel(model);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cursor.moveToFirst();
|
|
||||||
intent.putExtra("beginTime", cursor.getLong(0));
|
|
||||||
intent.putExtra("endTime", cursor.getLong(1));
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
Timber.e(e, e.getMessage());
|
|
||||||
Toast.makeText(activity, R.string.gcal_TEA_error, Toast.LENGTH_LONG).show();
|
|
||||||
} finally {
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
activity.startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshDisplayView() {
|
|
||||||
calendar.setTextColor(themeColor);
|
|
||||||
if (initialized) {
|
|
||||||
if (hasEvent) {
|
|
||||||
calendar.setText(R.string.gcal_TEA_showCalendar_label);
|
|
||||||
cancelButton.setVisibility(View.GONE);
|
|
||||||
} else if (calendarName != null) {
|
|
||||||
calendar.setText(calendarName);
|
|
||||||
cancelButton.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
calendar.setTextColor(unsetColor);
|
|
||||||
calendar.setText(R.string.gcal_TEA_addToCalendar_label);
|
|
||||||
cancelButton.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cancelButton.setVisibility(View.GONE);
|
|
||||||
if (TextUtils.isEmpty(model.getCalendarURI())) {
|
|
||||||
calendar.setTextColor(unsetColor);
|
|
||||||
calendar.setText(R.string.gcal_TEA_addToCalendar_label);
|
|
||||||
} else {
|
|
||||||
calendar.setText(R.string.gcal_TEA_showCalendar_label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getIcon() {
|
|
||||||
return R.drawable.ic_event_24dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectedCalendar(AndroidCalendar androidCalendar) {
|
|
||||||
this.calendarId = androidCalendar.getId();
|
|
||||||
this.calendarName = androidCalendar.getName();
|
|
||||||
refreshDisplayView();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dismiss() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
package com.todoroo.astrid.helper;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import com.todoroo.astrid.data.Task;
|
|
||||||
|
|
||||||
public interface TaskEditControlSet {
|
|
||||||
View getView();
|
|
||||||
|
|
||||||
void readFromTask(Task task);
|
|
||||||
|
|
||||||
void writeToModel(Task task);
|
|
||||||
|
|
||||||
int getIcon();
|
|
||||||
}
|
|
@ -1,110 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2012 Todoroo Inc
|
|
||||||
*
|
|
||||||
* See the file "LICENSE" for the full license governing this code.
|
|
||||||
*/
|
|
||||||
package com.todoroo.astrid.helper;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import com.todoroo.astrid.data.Task;
|
|
||||||
|
|
||||||
import org.tasks.R;
|
|
||||||
|
|
||||||
import static org.tasks.preferences.ResourceResolver.getData;
|
|
||||||
|
|
||||||
// --- interface
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for working with controls that alter task data
|
|
||||||
*/
|
|
||||||
public abstract class TaskEditControlSetBase implements TaskEditControlSet {
|
|
||||||
|
|
||||||
protected final Activity activity;
|
|
||||||
private final int viewLayout;
|
|
||||||
private boolean useTemplate;
|
|
||||||
private View view;
|
|
||||||
protected Task model;
|
|
||||||
protected boolean initialized = false;
|
|
||||||
protected final int themeColor;
|
|
||||||
protected final int unsetColor;
|
|
||||||
|
|
||||||
public TaskEditControlSetBase(Activity activity, int viewLayout) {
|
|
||||||
this(activity, viewLayout, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TaskEditControlSetBase(Activity activity, int viewLayout, boolean useTemplate) {
|
|
||||||
this.activity = activity;
|
|
||||||
this.viewLayout = viewLayout;
|
|
||||||
this.useTemplate = useTemplate;
|
|
||||||
if (viewLayout == -1) {
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
themeColor = getData(activity, R.attr.asTextColor);
|
|
||||||
unsetColor = getData(activity, R.attr.asTextColorHint);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected View inflateWithTemplate(int layout) {
|
|
||||||
LayoutInflater layoutInflater = LayoutInflater.from(activity);
|
|
||||||
View template = layoutInflater.inflate(R.layout.control_set_template, null);
|
|
||||||
LinearLayout content = (LinearLayout) template.findViewById(R.id.content);
|
|
||||||
content.addView(layoutInflater.inflate(layout, null));
|
|
||||||
return template;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View getView() {
|
|
||||||
if (view == null && !initialized) {
|
|
||||||
if (viewLayout != -1) {
|
|
||||||
view = useTemplate ? inflateWithTemplate(viewLayout) : LayoutInflater.from(activity).inflate(viewLayout, null);
|
|
||||||
afterInflate();
|
|
||||||
}
|
|
||||||
if (model != null) {
|
|
||||||
readFromTaskOnInitialize();
|
|
||||||
}
|
|
||||||
this.initialized = true;
|
|
||||||
}
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read data from model to update the control set
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void readFromTask(Task task) {
|
|
||||||
this.model = task;
|
|
||||||
if (initialized) {
|
|
||||||
readFromTaskOnInitialize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called once to setup the ui with data from the task
|
|
||||||
*/
|
|
||||||
protected abstract void readFromTaskOnInitialize();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write data from control set to model
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void writeToModel(Task task) {
|
|
||||||
if (initialized) {
|
|
||||||
writeToModelAfterInitialized(task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write to model, if initialization logic has been called
|
|
||||||
*/
|
|
||||||
protected abstract void writeToModelAfterInitialized(Task task);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when views need to be inflated
|
|
||||||
*/
|
|
||||||
protected abstract void afterInflate();
|
|
||||||
}
|
|
@ -1,132 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2012 Todoroo Inc
|
|
||||||
*
|
|
||||||
* See the file "LICENSE" for the full license governing this code.
|
|
||||||
*/
|
|
||||||
package com.todoroo.astrid.timers;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.support.v4.graphics.drawable.DrawableCompat;
|
|
||||||
import android.text.format.DateFormat;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
import android.widget.Chronometer;
|
|
||||||
import android.widget.Chronometer.OnChronometerTickListener;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import com.todoroo.andlib.utility.DateUtilities;
|
|
||||||
import com.todoroo.astrid.data.Task;
|
|
||||||
import com.todoroo.astrid.helper.TaskEditControlSetBase;
|
|
||||||
import com.todoroo.astrid.service.TaskService;
|
|
||||||
|
|
||||||
import org.tasks.R;
|
|
||||||
import org.tasks.notifications.NotificationManager;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class TimerActionControlSet extends TaskEditControlSetBase {
|
|
||||||
|
|
||||||
private final ImageView timerButton;
|
|
||||||
private final Chronometer chronometer;
|
|
||||||
private boolean timerActive;
|
|
||||||
private final List<TimerActionListener> listeners = new LinkedList<>();
|
|
||||||
|
|
||||||
public TimerActionControlSet(final NotificationManager notificationManager, final TaskService taskService, final Activity activity, View parent) {
|
|
||||||
super(activity, -1);
|
|
||||||
|
|
||||||
LinearLayout timerContainer = (LinearLayout) parent.findViewById(R.id.timer_container);
|
|
||||||
timerButton = (ImageView) parent.findViewById(R.id.timer_button);
|
|
||||||
OnClickListener timerListener = new OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (timerActive) {
|
|
||||||
TimerPlugin.stopTimer(notificationManager, taskService, activity, model);
|
|
||||||
|
|
||||||
for (TimerActionListener listener : listeners) {
|
|
||||||
listener.timerStopped(model);
|
|
||||||
}
|
|
||||||
chronometer.stop();
|
|
||||||
} else {
|
|
||||||
TimerPlugin.startTimer(notificationManager, taskService, activity, model);
|
|
||||||
for (TimerActionListener listener : listeners) {
|
|
||||||
listener.timerStarted(model);
|
|
||||||
}
|
|
||||||
chronometer.start();
|
|
||||||
}
|
|
||||||
timerActive = !timerActive;
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
timerContainer.setOnClickListener(timerListener);
|
|
||||||
chronometer = (Chronometer) parent.findViewById(R.id.timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void readFromTaskOnInitialize() {
|
|
||||||
timerActive = model.getTimerStart() != 0;
|
|
||||||
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void afterInflate() {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void writeToModelAfterInitialized(Task task) {
|
|
||||||
// Nothing to do here
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDisplay() {
|
|
||||||
int drawableRes = timerActive ? R.drawable.ic_pause_24dp : R.drawable.ic_play_arrow_24dp;
|
|
||||||
final Drawable drawable = DrawableCompat.wrap(activity.getResources().getDrawable(drawableRes));
|
|
||||||
DrawableCompat.setTint(drawable, activity.getResources().getColor(android.R.color.white));
|
|
||||||
timerButton.setImageDrawable(drawable);
|
|
||||||
|
|
||||||
long elapsed = model.getElapsedSeconds() * 1000L;
|
|
||||||
if (timerActive) {
|
|
||||||
chronometer.setVisibility(View.VISIBLE);
|
|
||||||
elapsed += DateUtilities.now() - model.getTimerStart();
|
|
||||||
chronometer.setBase(SystemClock.elapsedRealtime() - elapsed);
|
|
||||||
if (elapsed > DateUtilities.ONE_DAY) {
|
|
||||||
chronometer.setOnChronometerTickListener(new OnChronometerTickListener() {
|
|
||||||
@Override
|
|
||||||
public void onChronometerTick(Chronometer cArg) {
|
|
||||||
long t = SystemClock.elapsedRealtime() - cArg.getBase();
|
|
||||||
cArg.setText(DateFormat.format("d'd' h:mm", t)); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
chronometer.start();
|
|
||||||
} else {
|
|
||||||
chronometer.setVisibility(View.GONE);
|
|
||||||
chronometer.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getIcon() {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface TimerActionListener {
|
|
||||||
void timerStopped(Task task);
|
|
||||||
void timerStarted(Task task);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addListener(TimerActionListener listener) {
|
|
||||||
this.listeners.add(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeListener(TimerActionListener listener) {
|
|
||||||
if (listeners.contains(listener)) {
|
|
||||||
listeners.remove(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.todoroo.astrid.timers;
|
||||||
|
|
||||||
|
import com.todoroo.astrid.data.Task;
|
||||||
|
|
||||||
|
public interface TimerActionListener {
|
||||||
|
void timerStopped(Task task);
|
||||||
|
void timerStarted(Task task);
|
||||||
|
}
|
@ -1,32 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2012 Todoroo Inc
|
|
||||||
*
|
|
||||||
* See the file "LICENSE" for the full license governing this code.
|
|
||||||
*/
|
|
||||||
package com.todoroo.astrid.ui;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
|
|
||||||
import org.tasks.R;
|
|
||||||
|
|
||||||
public class DeadlineNumberPicker extends NumberPicker {
|
|
||||||
|
|
||||||
public DeadlineNumberPicker(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeadlineNumberPicker(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int getLayout() {
|
|
||||||
return R.layout.deadline_number_picker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int getMaxDigits() {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2012 Todoroo Inc
|
|
||||||
*
|
|
||||||
* See the file "LICENSE" for the full license governing this code.
|
|
||||||
*/
|
|
||||||
package com.todoroo.astrid.ui;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.widget.EditText;
|
|
||||||
|
|
||||||
import com.todoroo.astrid.data.Task;
|
|
||||||
import com.todoroo.astrid.helper.TaskEditControlSetBase;
|
|
||||||
|
|
||||||
import org.tasks.R;
|
|
||||||
|
|
||||||
public class DescriptionControlSet extends TaskEditControlSetBase {
|
|
||||||
|
|
||||||
protected EditText editText;
|
|
||||||
|
|
||||||
public DescriptionControlSet(Activity activity) {
|
|
||||||
super(activity, R.layout.control_set_description);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void afterInflate() {
|
|
||||||
editText = (EditText) getView().findViewById(R.id.notes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void readFromTaskOnInitialize() {
|
|
||||||
editText.setTextKeepState(model.getNotes());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void writeToModelAfterInitialized(Task task) {
|
|
||||||
task.setNotes(editText.getText().toString().trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getIcon() {
|
|
||||||
return R.drawable.ic_event_note_24dp;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,130 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2012 Todoroo Inc
|
|
||||||
*
|
|
||||||
* See the file "LICENSE" for the full license governing this code.
|
|
||||||
*/
|
|
||||||
package com.todoroo.astrid.ui;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
|
|
||||||
import com.todoroo.astrid.data.Task;
|
|
||||||
import com.todoroo.astrid.helper.TaskEditControlSetBase;
|
|
||||||
|
|
||||||
import org.tasks.dialogs.DialogBuilder;
|
|
||||||
import org.tasks.preferences.ActivityPreferences;
|
|
||||||
|
|
||||||
public abstract class PopupControlSet extends TaskEditControlSetBase {
|
|
||||||
|
|
||||||
protected final View displayView;
|
|
||||||
protected final ActivityPreferences preferences;
|
|
||||||
private DialogBuilder dialogBuilder;
|
|
||||||
protected AlertDialog dialog;
|
|
||||||
private final String titleString;
|
|
||||||
|
|
||||||
public interface PopupDialogClickListener {
|
|
||||||
boolean onClick(DialogInterface d, int which);
|
|
||||||
}
|
|
||||||
|
|
||||||
final PopupDialogClickListener okListener = new PopupDialogClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onClick(DialogInterface d, int which) {
|
|
||||||
onOkClick();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
final DialogInterface.OnCancelListener cancelListener = new DialogInterface.OnCancelListener() {
|
|
||||||
@Override
|
|
||||||
public void onCancel(DialogInterface d) {
|
|
||||||
onCancelClick();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public PopupControlSet(ActivityPreferences preferences, Activity activity, int viewLayout,
|
|
||||||
int taskEditViewLayout, final int title, DialogBuilder dialogBuilder) {
|
|
||||||
super(activity, viewLayout, false);
|
|
||||||
this.preferences = preferences;
|
|
||||||
this.dialogBuilder = dialogBuilder;
|
|
||||||
if (taskEditViewLayout != -1) {
|
|
||||||
this.displayView = inflateWithTemplate(taskEditViewLayout);
|
|
||||||
} else {
|
|
||||||
this.displayView = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
titleString = (title > 0) ? activity.getString(title) : ""; //$NON-NLS-1$
|
|
||||||
|
|
||||||
if (displayView != null) {
|
|
||||||
displayView.setOnClickListener(getDisplayClickListener());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View getView() {
|
|
||||||
return displayView;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected View getDialogView() {
|
|
||||||
return super.getView();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Dialog buildDialog(String title, final PopupDialogClickListener okClickListener, DialogInterface.OnCancelListener cancelClickListener) {
|
|
||||||
AlertDialog.Builder builder = dialogBuilder.newDialog()
|
|
||||||
.setView(getDialogView())
|
|
||||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
if (okClickListener.onClick(dialog, 0)) {
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.setOnCancelListener(cancelClickListener);
|
|
||||||
dialog = builder.show();
|
|
||||||
return dialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected OnClickListener getDisplayClickListener() {
|
|
||||||
return new OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (dialog == null) {
|
|
||||||
buildDialog(titleString, okListener, cancelListener);
|
|
||||||
}
|
|
||||||
dialog.show();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onOkClick() {
|
|
||||||
refreshDisplayView();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onCancelClick() {
|
|
||||||
refreshDisplayView();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dialog getDialog() {
|
|
||||||
return dialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToModel(Task task) {
|
|
||||||
if (initialized && dialog != null) {
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
super.writeToModel(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readFromTask(Task task) {
|
|
||||||
super.readFromTask(task);
|
|
||||||
refreshDisplayView();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void refreshDisplayView();
|
|
||||||
}
|
|
@ -0,0 +1,70 @@
|
|||||||
|
package org.tasks.activities;
|
||||||
|
|
||||||
|
import android.app.FragmentManager;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
|
||||||
|
|
||||||
|
import org.tasks.R;
|
||||||
|
import org.tasks.dialogs.MyDatePickerDialog;
|
||||||
|
import org.tasks.injection.InjectingAppCompatActivity;
|
||||||
|
import org.tasks.preferences.ActivityPreferences;
|
||||||
|
import org.tasks.time.DateTime;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.tasks.time.DateTimeUtils.currentTimeMillis;
|
||||||
|
|
||||||
|
public class DatePickerActivity extends InjectingAppCompatActivity
|
||||||
|
implements DatePickerDialog.OnDateSetListener, DialogInterface.OnDismissListener {
|
||||||
|
|
||||||
|
private static final String FRAG_TAG_DATE_PICKER = "frag_tag_date_picker";
|
||||||
|
|
||||||
|
public static final String EXTRA_TIMESTAMP = "extra_timestamp";
|
||||||
|
|
||||||
|
@Inject ActivityPreferences preferences;
|
||||||
|
|
||||||
|
private DateTime initial;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
preferences.applyTheme();
|
||||||
|
|
||||||
|
long timestamp = getIntent().getLongExtra(EXTRA_TIMESTAMP, currentTimeMillis());
|
||||||
|
initial = timestamp > 0 ? new DateTime(timestamp) : new DateTime().startOfDay();
|
||||||
|
|
||||||
|
FragmentManager fragmentManager = getFragmentManager();
|
||||||
|
MyDatePickerDialog dialog = (MyDatePickerDialog) fragmentManager.findFragmentByTag(FRAG_TAG_DATE_PICKER);
|
||||||
|
if (dialog == null) {
|
||||||
|
dialog = new MyDatePickerDialog();
|
||||||
|
dialog.initialize(null, initial.getYear(), initial.getMonthOfYear() - 1, initial.getDayOfMonth());
|
||||||
|
if (preferences.isDarkTheme()) {
|
||||||
|
dialog.setAccentColor(getResources().getColor(R.color.black_text_hint));
|
||||||
|
}
|
||||||
|
dialog.show(fragmentManager, FRAG_TAG_DATE_PICKER);
|
||||||
|
}
|
||||||
|
dialog.setOnDismissListener(this);
|
||||||
|
dialog.setOnDateSetListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDateSet(DatePickerDialog view, final int year, final int monthOfYear, final int dayOfMonth) {
|
||||||
|
setResult(RESULT_OK, new Intent() {{
|
||||||
|
putExtra(EXTRA_TIMESTAMP, initial
|
||||||
|
.withYear(year)
|
||||||
|
.withMonthOfYear(monthOfYear + 1)
|
||||||
|
.withDayOfMonth(dayOfMonth)
|
||||||
|
.getMillis());
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDismiss(DialogInterface dialog) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,246 @@
|
|||||||
|
package org.tasks.ui;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.todoroo.astrid.data.Task;
|
||||||
|
import com.todoroo.astrid.gcal.AndroidCalendar;
|
||||||
|
import com.todoroo.astrid.gcal.GCalHelper;
|
||||||
|
|
||||||
|
import org.tasks.R;
|
||||||
|
import org.tasks.activities.CalendarSelectionActivity;
|
||||||
|
import org.tasks.injection.ForActivity;
|
||||||
|
import org.tasks.preferences.Preferences;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import butterknife.Bind;
|
||||||
|
import butterknife.OnClick;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||||
|
|
||||||
|
public class CalendarControlSet extends TaskEditControlFragment {
|
||||||
|
|
||||||
|
private static final int REQUEST_CODE_CALENDAR = 70;
|
||||||
|
private static final String EXTRA_URI = "extra_uri";
|
||||||
|
private static final String EXTRA_ID = "extra_id";
|
||||||
|
private static final String EXTRA_NAME = "extra_name";
|
||||||
|
|
||||||
|
@Bind(R.id.clear) View cancelButton;
|
||||||
|
@Bind(R.id.calendar_display_which) TextView calendar;
|
||||||
|
|
||||||
|
@Inject GCalHelper gcalHelper;
|
||||||
|
@Inject Preferences preferences;
|
||||||
|
@Inject @ForActivity Context context;
|
||||||
|
|
||||||
|
private String calendarId;
|
||||||
|
private String calendarName;
|
||||||
|
private String eventUri;
|
||||||
|
private boolean isNewTask;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
View view = super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
eventUri = savedInstanceState.getString(EXTRA_URI);
|
||||||
|
calendarName = savedInstanceState.getString(EXTRA_NAME);
|
||||||
|
calendarId = savedInstanceState.getString(EXTRA_ID);
|
||||||
|
} else if (isNewTask) {
|
||||||
|
calendarId = preferences.getDefaultCalendar();
|
||||||
|
if (!Strings.isNullOrEmpty(calendarId)) {
|
||||||
|
AndroidCalendar defaultCalendar = gcalHelper.getCalendar(calendarId);
|
||||||
|
if (defaultCalendar == null) {
|
||||||
|
calendarId = null;
|
||||||
|
} else {
|
||||||
|
calendarName = defaultCalendar.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!calendarEntryExists(eventUri)) {
|
||||||
|
eventUri = null;
|
||||||
|
}
|
||||||
|
refreshDisplayView();
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getLayout() {
|
||||||
|
return R.layout.control_set_gcal_display;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getIcon() {
|
||||||
|
return R.drawable.ic_event_24dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(boolean isNewTask, Task task) {
|
||||||
|
this.isNewTask = isNewTask;
|
||||||
|
eventUri = task.getCalendarURI();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(Task task) {
|
||||||
|
if (!task.hasDueDate()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (calendarEntryExists(task.getCalendarURI())) {
|
||||||
|
ContentResolver cr = context.getContentResolver();
|
||||||
|
try {
|
||||||
|
ContentValues updateValues = new ContentValues();
|
||||||
|
|
||||||
|
// check if we need to update the item
|
||||||
|
ContentValues setValues = task.getSetValues();
|
||||||
|
if(setValues.containsKey(Task.TITLE.name)) {
|
||||||
|
updateValues.put("title", task.getTitle());
|
||||||
|
}
|
||||||
|
if(setValues.containsKey(Task.NOTES.name)) {
|
||||||
|
updateValues.put("description", task.getNotes());
|
||||||
|
}
|
||||||
|
if(setValues.containsKey(Task.DUE_DATE.name) || setValues.containsKey(Task.ESTIMATED_SECONDS.name)) {
|
||||||
|
gcalHelper.createStartAndEndDate(task, updateValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
cr.update(Uri.parse(task.getCalendarURI()), updateValues, null, null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Timber.e(e, "unable-to-update-calendar: %s", task.getCalendarURI());
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isNullOrEmpty(calendarId)) {
|
||||||
|
ContentResolver cr = context.getContentResolver();
|
||||||
|
try{
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put("calendar_id", calendarId);
|
||||||
|
Uri uri = gcalHelper.createTaskEvent(task, cr, values);
|
||||||
|
if(uri != null) {
|
||||||
|
task.setCalendarUri(uri.toString());
|
||||||
|
// pop up the new event
|
||||||
|
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||||
|
intent.putExtra("beginTime", values.getAsLong("dtstart"));
|
||||||
|
intent.putExtra("endTime", values.getAsLong("dtend"));
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Timber.e(e, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
|
||||||
|
outState.putString(EXTRA_URI, eventUri);
|
||||||
|
outState.putString(EXTRA_NAME, calendarName);
|
||||||
|
outState.putString(EXTRA_ID, calendarId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.clear)
|
||||||
|
void clearCalendar(View view) {
|
||||||
|
calendarName = null;
|
||||||
|
calendarId = null;
|
||||||
|
eventUri = null;
|
||||||
|
refreshDisplayView();
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.calendar_display_which)
|
||||||
|
void clickCalendar(View view) {
|
||||||
|
if (Strings.isNullOrEmpty(eventUri)) {
|
||||||
|
startActivityForResult(new Intent(context, CalendarSelectionActivity.class), REQUEST_CODE_CALENDAR);
|
||||||
|
} else {
|
||||||
|
ContentResolver cr = getActivity().getContentResolver();
|
||||||
|
Uri uri = Uri.parse(eventUri);
|
||||||
|
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||||
|
Cursor cursor = cr.query(uri, new String[] { "dtstart", "dtend" }, null, null, null);
|
||||||
|
try {
|
||||||
|
if(cursor.getCount() == 0) {
|
||||||
|
// event no longer exists
|
||||||
|
eventUri = null;
|
||||||
|
refreshDisplayView();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cursor.moveToFirst();
|
||||||
|
intent.putExtra("beginTime", cursor.getLong(0));
|
||||||
|
intent.putExtra("endTime", cursor.getLong(1));
|
||||||
|
} catch (Exception e) {
|
||||||
|
Timber.e(e, e.getMessage());
|
||||||
|
Toast.makeText(getActivity(), R.string.gcal_TEA_error, Toast.LENGTH_LONG).show();
|
||||||
|
} finally {
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
if (requestCode == REQUEST_CODE_CALENDAR) {
|
||||||
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
|
calendarId = data.getStringExtra(CalendarSelectionActivity.EXTRA_CALENDAR_ID);
|
||||||
|
calendarName = data.getStringExtra(CalendarSelectionActivity.EXTRA_CALENDAR_NAME);
|
||||||
|
refreshDisplayView();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshDisplayView() {
|
||||||
|
if (!Strings.isNullOrEmpty(eventUri)) {
|
||||||
|
calendar.setAlpha(1.0f);
|
||||||
|
calendar.setText(R.string.gcal_TEA_showCalendar_label);
|
||||||
|
cancelButton.setVisibility(View.GONE);
|
||||||
|
} else if (calendarName != null) {
|
||||||
|
calendar.setAlpha(1.0f);
|
||||||
|
calendar.setText(calendarName);
|
||||||
|
cancelButton.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
calendar.setAlpha(0.5f);
|
||||||
|
calendar.setText(R.string.gcal_TEA_addToCalendar_label);
|
||||||
|
cancelButton.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean calendarEntryExists(String eventUri) {
|
||||||
|
if (isNullOrEmpty(eventUri)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Uri uri = Uri.parse(eventUri);
|
||||||
|
ContentResolver contentResolver = context.getContentResolver();
|
||||||
|
Cursor cursor = contentResolver.query(uri, new String[]{"dtstart"}, null, null, null);
|
||||||
|
try {
|
||||||
|
if (cursor.getCount() != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
} catch(Exception e) {
|
||||||
|
Timber.e(e, "%s: %s", eventUri, e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
package org.tasks.ui;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.EditText;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.todoroo.astrid.data.Task;
|
||||||
|
|
||||||
|
import org.tasks.R;
|
||||||
|
|
||||||
|
import butterknife.Bind;
|
||||||
|
import butterknife.OnTextChanged;
|
||||||
|
|
||||||
|
public class DescriptionControlSet extends TaskEditControlFragment {
|
||||||
|
|
||||||
|
private static final String EXTRA_DESCRIPTION = "extra_description";
|
||||||
|
|
||||||
|
@Bind(R.id.notes) EditText editText;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
View view = super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
description = savedInstanceState.getString(EXTRA_DESCRIPTION);
|
||||||
|
}
|
||||||
|
if (!Strings.isNullOrEmpty(description)) {
|
||||||
|
editText.setTextKeepState(description);
|
||||||
|
}
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
|
||||||
|
outState.putString(EXTRA_DESCRIPTION, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getLayout() {
|
||||||
|
return R.layout.control_set_description;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getIcon() {
|
||||||
|
return R.drawable.ic_event_note_24dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnTextChanged(R.id.notes)
|
||||||
|
void textChanged(CharSequence text) {
|
||||||
|
description = text.toString().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(boolean isNewTask, Task task) {
|
||||||
|
description = task.getNotes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(Task task) {
|
||||||
|
task.setNotes(description);
|
||||||
|
}
|
||||||
|
}
|
@ -1,104 +1,115 @@
|
|||||||
package org.tasks.ui;
|
package org.tasks.ui;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.widget.AppCompatRadioButton;
|
import android.support.v7.widget.AppCompatRadioButton;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.RadioGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.CompoundButton;
|
||||||
|
|
||||||
import com.google.common.primitives.Ints;
|
|
||||||
import com.todoroo.astrid.data.Task;
|
import com.todoroo.astrid.data.Task;
|
||||||
import com.todoroo.astrid.helper.TaskEditControlSetBase;
|
|
||||||
|
|
||||||
import org.tasks.R;
|
import org.tasks.R;
|
||||||
|
|
||||||
import java.util.Collections;
|
import javax.inject.Inject;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class PriorityControlSet extends TaskEditControlSetBase {
|
import butterknife.Bind;
|
||||||
|
import butterknife.OnClick;
|
||||||
|
|
||||||
private final List<Integer> colors;
|
public class PriorityControlSet extends TaskEditControlFragment {
|
||||||
private final List<ImportanceChangedListener> listeners = new LinkedList<>();
|
|
||||||
private RadioGroup radioGroup;
|
|
||||||
|
|
||||||
public interface ImportanceChangedListener {
|
public interface OnPriorityChanged {
|
||||||
void importanceChanged(int i);
|
void onPriorityChange(int priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PriorityControlSet(Activity activity) {
|
private static final String EXTRA_PRIORITY = "extra_priority";
|
||||||
super(activity, R.layout.control_set_priority);
|
|
||||||
colors = Ints.asList(Task.getImportanceColors(activity.getResources()));
|
|
||||||
Collections.reverse(colors);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notifyImportanceChange(Integer i) {
|
@Inject CheckBoxes checkBoxes;
|
||||||
for (ImportanceChangedListener l : listeners) {
|
|
||||||
l.importanceChanged(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Integer getImportance(int checkedId) {
|
@Bind(R.id.priority_high) AppCompatRadioButton priorityHigh;
|
||||||
return getImportance(getView().findViewById(checkedId));
|
@Bind(R.id.priority_medium) AppCompatRadioButton priorityMedium;
|
||||||
}
|
@Bind(R.id.priority_low) AppCompatRadioButton priorityLow;
|
||||||
|
@Bind(R.id.priority_none) AppCompatRadioButton priorityNone;
|
||||||
|
|
||||||
|
private OnPriorityChanged callback;
|
||||||
|
private int priority;
|
||||||
|
|
||||||
private Integer getImportance(View view) {
|
@Override
|
||||||
return Integer.parseInt((String) view.getTag());
|
public void onAttach(Activity activity) {
|
||||||
|
super.onAttach(activity);
|
||||||
|
|
||||||
|
callback = (OnPriorityChanged) activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addListener(ImportanceChangedListener listener) {
|
@OnClick({R.id.priority_high, R.id.priority_medium, R.id.priority_low, R.id.priority_none})
|
||||||
listeners.add(listener);
|
void onImportanceChanged(CompoundButton button) {
|
||||||
|
callback.onPriorityChange(getPriority());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
protected void afterInflate() {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
final View view = getView();
|
final View view = super.onCreateView(inflater, container, savedInstanceState);
|
||||||
radioGroup = (RadioGroup) view.findViewById(R.id.importance_group);
|
if (savedInstanceState != null) {
|
||||||
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
|
priority = savedInstanceState.getInt(EXTRA_PRIORITY);
|
||||||
@Override
|
}
|
||||||
public void onCheckedChanged(RadioGroup group, int checkedId) {
|
if (priority == 0) {
|
||||||
notifyImportanceChange(getImportance(checkedId));
|
priorityHigh.setChecked(true);
|
||||||
}
|
} else if(priority == 1) {
|
||||||
});
|
priorityMedium.setChecked(true);
|
||||||
for (int i = 0; i < radioGroup.getChildCount(); i++) {
|
} else if(priority == 2) {
|
||||||
AppCompatRadioButton radioButton = (AppCompatRadioButton) radioGroup.getChildAt(i);
|
priorityLow.setChecked(true);
|
||||||
radioButton.setSupportButtonTintList(new ColorStateList(new int[][]{
|
} else {
|
||||||
new int[]{-android.R.attr.state_checked}, new int[]{android.R.attr.state_checked}},
|
priorityNone.setChecked(true);
|
||||||
new int[]{colors.get(i), colors.get(i)}));
|
}
|
||||||
}
|
tintRadioButton(priorityHigh, 0);
|
||||||
|
tintRadioButton(priorityMedium, 1);
|
||||||
|
tintRadioButton(priorityLow, 2);
|
||||||
|
tintRadioButton(priorityNone, 3);
|
||||||
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readFromTask(Task task) {
|
protected int getLayout() {
|
||||||
super.readFromTask(task);
|
return R.layout.control_set_priority;
|
||||||
setSelected(model.getImportance());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIcon() {
|
protected int getIcon() {
|
||||||
return R.drawable.ic_flag_24dp;
|
return R.drawable.ic_flag_24dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void readFromTaskOnInitialize() {
|
public void initialize(boolean isNewTask, Task task) {
|
||||||
setSelected(model.getImportance());
|
priority = task.getImportance();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSelected(int importance) {
|
@Override
|
||||||
if (radioGroup == null) {
|
public void apply(Task task) {
|
||||||
return;
|
task.setImportance(getPriority());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < radioGroup.getChildCount(); i++) {
|
private void tintRadioButton(AppCompatRadioButton radioButton, int priority) {
|
||||||
AppCompatRadioButton radioButton = (AppCompatRadioButton) radioGroup.getChildAt(i);
|
int color = checkBoxes.getPriorityColors().get(priority);
|
||||||
if (importance == getImportance(radioButton)) {
|
radioButton.setSupportButtonTintList(new ColorStateList(new int[][]{
|
||||||
radioButton.setChecked(true);
|
new int[]{-android.R.attr.state_checked}, new int[]{android.R.attr.state_checked}},
|
||||||
|
new int[]{color, color}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getPriority() {
|
||||||
|
if (priorityHigh.isChecked()) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (priorityMedium.isChecked()) {
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
if (priorityLow.isChecked()) {
|
||||||
@Override
|
return 2;
|
||||||
protected void writeToModelAfterInitialized(Task task) {
|
}
|
||||||
task.setImportance(getImportance(radioGroup.getCheckedRadioButtonId()));
|
return 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package org.tasks.ui;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import com.todoroo.astrid.data.Task;
|
||||||
|
|
||||||
|
import org.tasks.R;
|
||||||
|
import org.tasks.injection.InjectingFragment;
|
||||||
|
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
|
||||||
|
public abstract class TaskEditControlFragment extends InjectingFragment {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
final View view = inflater.inflate(R.layout.control_set_template, null);
|
||||||
|
LinearLayout content = (LinearLayout) view.findViewById(R.id.content);
|
||||||
|
content.addView(inflater.inflate(getLayout(), null));
|
||||||
|
ImageView icon = (ImageView) view.findViewById(R.id.icon);
|
||||||
|
icon.setImageResource(getIcon());
|
||||||
|
ButterKnife.bind(this, view);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract int getLayout();
|
||||||
|
|
||||||
|
protected abstract int getIcon();
|
||||||
|
|
||||||
|
public abstract void initialize(boolean isNewTask, Task task);
|
||||||
|
|
||||||
|
public abstract void apply(Task task);
|
||||||
|
}
|
@ -1,26 +0,0 @@
|
|||||||
<?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">
|
|
||||||
|
|
||||||
<item android:state_checked="false"
|
|
||||||
android:state_enabled="true"
|
|
||||||
android:drawable="@drawable/icn_check_off" />
|
|
||||||
<item android:state_checked="true"
|
|
||||||
android:state_enabled="true"
|
|
||||||
android:drawable="@drawable/icn_check_on" />
|
|
||||||
|
|
||||||
</selector>
|
|
@ -1,35 +0,0 @@
|
|||||||
<?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="@android:drawable/checkbox_off_background" />
|
|
||||||
<item android:state_checked="false" android:state_pressed="true"
|
|
||||||
android:state_enabled="true"
|
|
||||||
android:drawable="@android:drawable/checkbox_on_background" />
|
|
||||||
|
|
||||||
<item android:state_checked="false"
|
|
||||||
android:state_enabled="true"
|
|
||||||
android:drawable="@android:drawable/checkbox_off_background" />
|
|
||||||
<item android:state_checked="true"
|
|
||||||
android:state_enabled="true"
|
|
||||||
android:drawable="@android:drawable/checkbox_on_background" />
|
|
||||||
|
|
||||||
</selector>
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 610 B |
Binary file not shown.
Before Width: | Height: | Size: 1.4 KiB |
@ -1,52 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
**
|
|
||||||
** Copyright 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.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<com.todoroo.astrid.ui.NumberPickerButton android:id="@+id/increment"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="38dip"
|
|
||||||
android:src="@drawable/icn_arrow_up"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<EditText android:id="@+id/timepicker_input"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="40dip"
|
|
||||||
android:layout_weight="1"
|
|
||||||
style="?android:attr/textAppearanceLarge"
|
|
||||||
android:gravity="center"
|
|
||||||
android:inputType="phone"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:textColor="?attr/asThemeTextColor"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<com.todoroo.astrid.ui.NumberPickerButton android:id="@+id/decrement"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="38dip"
|
|
||||||
android:src="@drawable/icn_arrow_down"
|
|
||||||
android:paddingTop="15dip"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</merge>
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue