Changed directory structure

This commit is contained in:
2017-12-13 21:37:19 +01:00
parent cb80cc45b1
commit cd77819dec
142 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wismna.geoffroy.donext">
<application
android:name=".DoNext"
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<meta-data
android:name="android.max_aspect"
android:value="2.1" />
<activity
android:name=".activities.MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activities.SettingsActivity"
android:label="@string/action_settings"
android:parentActivityName=".activities.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity" />
</activity>
<activity
android:name=".activities.TaskListActivity"
android:label="@string/action_editTabs"
android:parentActivityName=".activities.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity" />
</activity>
<activity
android:name=".activities.AboutActivity"
android:label="@string/action_about"
android:parentActivityName=".activities.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity" />
</activity>
<activity
android:name=".activities.TodayActivity"
android:label="@string/title_activity_today"
android:parentActivityName=".activities.MainActivity"
android:theme="@style/AppTheme.NoActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity" />
</activity>
<activity android:name=".activities.HistoryActivity" />
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,18 @@
package com.wismna.geoffroy.donext;
import android.app.Application;
import net.danlew.android.joda.JodaTimeAndroid;
/**
* Created by bg45 on 2017-03-15.
* Application class, used to initialize Joda Time
*/
public class DoNext extends Application {
@Override
public void onCreate() {
super.onCreate();
JodaTimeAndroid.init(this);
}
}

View File

@@ -0,0 +1,25 @@
package com.wismna.geoffroy.donext.activities;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import com.wismna.geoffroy.donext.BuildConfig;
import com.wismna.geoffroy.donext.R;
public class AboutActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
TextView versionDonext = (TextView) findViewById(R.id.version_donext);
versionDonext.setText(getResources().getString(R.string.about_version_donext, BuildConfig.VERSION_NAME));
TextView versionAndroid = (TextView) findViewById(R.id.version_android);
versionAndroid.setText(getResources().getString(R.string.about_version_android, Build.VERSION.SDK_INT));
}
}

View File

@@ -0,0 +1,171 @@
package com.wismna.geoffroy.donext.activities;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import com.wismna.geoffroy.donext.R;
import com.wismna.geoffroy.donext.fragments.MainFragment;
import com.wismna.geoffroy.donext.fragments.TaskFormDialogFragment;
import com.wismna.geoffroy.donext.fragments.TaskListsFragment;
import com.wismna.geoffroy.donext.fragments.TasksFragment;
/**
* Main Activity class
*/
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
// Handles today list
MenuItem todayListItem = menu.findItem(R.id.action_todayList);
if (todayListItem == null) return false;
todayListItem.setVisible(sharedPref.getBoolean("pref_conf_today_enable", false));
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
return id == R.id.action_settings || super.onOptionsItemSelected(item);
}
/** Called when the user clicks on the Today List button */
public void showTodayList(MenuItem item) {
Intent intent = new Intent(this, TodayActivity.class);
startActivity(intent);
}
/** Called when the user clicks on the Change Layout button */
public void changeLayout(MenuItem item) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPref.edit();
String layoutTypeString = sharedPref.getString("pref_conf_task_layout", "1");
int layoutType = Integer.valueOf(layoutTypeString);
editor.putString("pref_conf_task_layout", String.valueOf(layoutType % 2 + 1));
editor.apply();
// Update the ViewPagerAdapter to refresh all tabs
MainFragment fragment = getMainFragment();
fragment.getViewPager().getAdapter().notifyDataSetChanged();
//mSectionsPagerAdapter.notifyDataSetChanged();
}
/** Called when the user clicks the Edit Lists button */
public void openTaskLists(MenuItem menuItem) {
/*Intent intent = new Intent(this, TaskListActivity.class);
startActivity(intent);*/
// Create the fragment
TaskListsFragment taskListFragment = new TaskListsFragment();
String title = getString(R.string.action_edit_task);
FragmentManager fragmentManager = getSupportFragmentManager();
// Set the arguments
Bundle args = new Bundle();
args.putInt("button_count", 1);
args.putString("button_negative", getString(R.string.task_list_ok));
taskListFragment.setArguments(args);
if (getResources().getBoolean(R.bool.large_layout))
taskListFragment.show(fragmentManager, title);
else {
// The device is smaller, so show the fragment fullscreen
FragmentTransaction transaction = fragmentManager.beginTransaction();
// For a little polish, specify a transition animation
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// To make it fullscreen, use the 'content' root view as the container
// for the fragment, which is always the root view for the activity
transaction.add(android.R.id.content, taskListFragment, title)
.addToBackStack(null).commit();
}
}
/** Called when the user clicks the History button*/
public void openHistory(MenuItem item) {
MainFragment fragment = getMainFragment();
fragment.toggleHistory();
}
/** Called when the user clicks the Settings button */
public void openSettings(MenuItem menuItem) {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
}
/** Called when the user clicks the About button */
public void openAbout(MenuItem menuItem) {
Intent intent = new Intent(this, AboutActivity.class);
startActivity(intent);
}
/** Called when user clicks on the New Task floating button */
public void onNewTaskClick(View view) {
MainFragment fragment = getMainFragment();
ViewPager viewPager = fragment.getViewPager();
int currentTabPosition = viewPager.getCurrentItem();
MainFragment.SectionsPagerAdapter pagerAdapter = (MainFragment.SectionsPagerAdapter) viewPager.getAdapter();
TaskFormDialogFragment taskDialogFragment = TaskFormDialogFragment.newInstance(null,
pagerAdapter.getAllItems(),
(TasksFragment) pagerAdapter.getRegisteredFragment(currentTabPosition));
// Set some configuration values for the tab
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
Bundle args = new Bundle();
args.putInt("list", currentTabPosition);
args.putBoolean("today", sharedPref.getBoolean("pref_conf_today_enable", false));
args.putInt("button_count", 2);
args.putString("button_positive", getString(R.string.new_task_save));
args.putString("button_negative", getString(R.string.new_task_cancel));
args.putString("button_neutral", getString(R.string.new_task_delete));
taskDialogFragment.setArguments(args);
String title = getString(R.string.action_new_task);
FragmentManager fragmentManager = getSupportFragmentManager();
if (getResources().getBoolean(R.bool.large_layout))
taskDialogFragment.show(fragmentManager, title);
else {
// The device is smaller, so show the fragment fullscreen
FragmentTransaction transaction = fragmentManager.beginTransaction();
// For a little polish, specify a transition animation
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// To make it fullscreen, use the 'content' root view as the container
// for the fragment, which is always the root view for the activity
transaction.add(android.R.id.content, taskDialogFragment, title)
.addToBackStack(null).commit();
}
}
private MainFragment getMainFragment(){
FragmentManager manager = getSupportFragmentManager();
return (MainFragment)manager.findFragmentById(R.id.fragment_main);
}
}

View File

@@ -0,0 +1,32 @@
package com.wismna.geoffroy.donext.activities;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import com.wismna.geoffroy.donext.R;
public class SettingsActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display the preferences fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
}
public static class SettingsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
}
}
}

View File

@@ -0,0 +1,14 @@
package com.wismna.geoffroy.donext.activities;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import com.wismna.geoffroy.donext.R;
public class TaskListActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tasklists);
}
}

View File

@@ -0,0 +1,106 @@
package com.wismna.geoffroy.donext.activities;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import com.wismna.geoffroy.donext.R;
import com.wismna.geoffroy.donext.adapters.TaskRecyclerViewAdapter;
import com.wismna.geoffroy.donext.database.TaskDataAccess;
import com.wismna.geoffroy.donext.fragments.TodayFormDialogFragment;
public class TodayActivity extends AppCompatActivity
implements TodayFormDialogFragment.TodayTaskListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_today);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Get a support ActionBar corresponding to this toolbar
ActionBar ab = getSupportActionBar();
if (ab != null) {
// Enable the Up button
ab.setDisplayHomeAsUpEnabled(true);
ab.setHomeButtonEnabled(true);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_today, menu);
return true;
}
/** Called when the user clicks on the Change Layout button */
public void changeLayout(MenuItem item) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPref.edit();
String layoutTypeString = sharedPref.getString("pref_conf_task_layout", "1");
int layoutType = Integer.valueOf(layoutTypeString);
editor.putString("pref_conf_task_layout", String.valueOf(layoutType % 2 + 1));
editor.apply();
// TODO: find a less ugly way to refresh the list
// Update the ViewPagerAdapter to refresh all tabs
this.recreate();
}
public void onNewTaskClick(View view) {
TodayFormDialogFragment taskDialogFragment =
TodayFormDialogFragment.newInstance(TodayActivity.this);
boolean isLargeLayout = getResources().getBoolean(R.bool.large_layout);
// Set some configuration values for the dialog
Bundle args = new Bundle();
args.putBoolean("layout", isLargeLayout);
args.putString("button_positive", getString(R.string.new_task_save));
args.putString("button_negative", getString(R.string.new_task_cancel));
taskDialogFragment.setArguments(args);
String title = getString(R.string.action_today_select);
FragmentManager fragmentManager = getSupportFragmentManager();
if (isLargeLayout)
taskDialogFragment.show(fragmentManager, title);
else {
// The device is smaller, so show the fragment fullscreen
FragmentTransaction transaction = fragmentManager.beginTransaction();
// For a little polish, specify a transition animation
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// To make it fullscreen, use the 'content' root view as the container
// for the fragment, which is always the root view for the activity
transaction.add(android.R.id.content, taskDialogFragment, title)
.addToBackStack(null).commit();
}
}
@Override
public void onTodayTaskDialogPositiveClick(View dialogView) {
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setEnabled(false);
}
@Override
public void onTodayTasksUpdated() {
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setEnabled(true);
try (TaskDataAccess taskDataAccess = new TaskDataAccess(this)) {
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.task_list_view);
((TaskRecyclerViewAdapter)recyclerView.getAdapter()).setItems(taskDataAccess.getTodayTasks());
}
}
}

View File

@@ -0,0 +1,48 @@
package com.wismna.geoffroy.donext.adapters;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.util.SparseArray;
import android.view.ViewGroup;
/**
* Created by geoffroy on 15-11-28.
* Extension of FragmentStatePagerAdapter which intelligently caches
* all active fragments and manages the fragment lifecycles.
* Usage involves extending from SmartFragmentStatePagerAdapter as you would any other PagerAdapter.
*/
public abstract class SmartFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
// Sparse array to keep track of registered fragments in memory
private final SparseArray<Fragment> registeredFragments = new SparseArray<>();
public SmartFragmentStatePagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
// Register the fragment when the item is instantiated
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
// Unregister when the item is inactive
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
// Returns the fragment for the position (if instantiated)
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}

View File

@@ -0,0 +1,161 @@
package com.wismna.geoffroy.donext.adapters;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import com.wismna.geoffroy.donext.R;
import com.wismna.geoffroy.donext.dao.TaskList;
import com.wismna.geoffroy.donext.helpers.TaskListTouchHelper;
import java.util.Collections;
import java.util.List;
/**
* {@link RecyclerView.Adapter} that can display a {@link TaskList}.
*/
public class TaskListRecyclerViewAdapter extends RecyclerView.Adapter<TaskListRecyclerViewAdapter.ViewHolder>
implements TaskListTouchHelper.TaskListTouchHelperAdapter {
public interface TaskListRecyclerViewAdapterListener {
void onEditTextLoseFocus(TaskList taskList);
void onClickDeleteButton(int position, long id);
void onItemMove(long fromTaskId, long toTaskId, int fromPosition, int toPosition);
void onStartDrag(RecyclerView.ViewHolder viewHolder);
}
private final List<TaskList> mValues;
private final TaskListRecyclerViewAdapterListener mListener;
public TaskListRecyclerViewAdapter(List<TaskList> items,
TaskListRecyclerViewAdapterListener listener) {
mValues = items;
mListener = listener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_tasklist, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position);
holder.mTaskCountView.setText(String.valueOf(mValues.get(position).getTaskCount()));
holder.mTaskNameView.setText(mValues.get(position).getName());
holder.handleView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEventCompat.getActionMasked(event) ==
MotionEvent.ACTION_DOWN) {
mListener.onStartDrag(holder);
}
return false;
}
});
// Handle inline name change
holder.mTaskNameView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
EditText editText = (EditText) v;
String name = editText.getText().toString();
if (!hasFocus && !holder.mItem.getName().matches(name)) {
holder.mItem.setName(name);
update(holder.mItem, holder.getAdapterPosition());
mListener.onEditTextLoseFocus(holder.mItem);
}
}
});
// Handle click on delete button
holder.mTaskDeleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Disable the OnFocusChanged listener as it is now pointless and harmful
holder.mTaskNameView.setOnFocusChangeListener(null);
//remove(position);
mListener.onClickDeleteButton(holder.getAdapterPosition(), holder.mItem.getId());
}
});
}
@Override
public int getItemCount() {
return mValues.size();
}
public void add(TaskList item, int position) {
mValues.add(position, item);
notifyItemInserted(position);
}
public void remove(int position) {
mValues.remove(position);
notifyItemRemoved(position);
}
private void update(TaskList item, int position) {
mValues.set(position, item);
notifyItemChanged(position);
}
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
long fromTaskId = mValues.get(fromPosition).getId();
long toTaskId = mValues.get(toPosition).getId();
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(mValues, i, i + 1);
}
}
else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(mValues, i, i - 1);
}
}
mListener.onItemMove(fromTaskId, toTaskId, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
return true;
}
class ViewHolder extends RecyclerView.ViewHolder {
final View mView;
final ImageView handleView;
final TextView mTaskCountView;
final TextView mTaskNameView;
final Button mTaskDeleteButton;
TaskList mItem;
ViewHolder(View view) {
super(view);
mView = view;
handleView = (ImageView) itemView.findViewById(R.id.handle);
mTaskCountView = (TextView) view.findViewById(R.id.task_list_count);
mTaskNameView = (TextView) view.findViewById(R.id.task_list_name);
mTaskDeleteButton = (Button) view.findViewById(R.id.task_list_delete);
}
@Override
public String toString() {
return super.toString() + " '" + mTaskNameView.getText() + "'";
}
}
}

View File

@@ -0,0 +1,174 @@
package com.wismna.geoffroy.donext.adapters;
import android.graphics.Color;
import android.graphics.Typeface;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.wismna.geoffroy.donext.R;
import com.wismna.geoffroy.donext.dao.Task;
import org.joda.time.LocalDate;
import java.util.List;
/**
* {@link RecyclerView.Adapter} that can display a {@link Task}.
*/
public class TaskRecyclerViewAdapter extends RecyclerView.Adapter<TaskRecyclerViewAdapter.SimpleViewHolder> {
private List<Task> mValues;
private int viewType;
private boolean mIsToday;
public TaskRecyclerViewAdapter(List<Task> items, int viewType, boolean isToday) {
mValues = items;
mIsToday = isToday;
this.viewType = viewType;
}
@Override
public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType)
{
case 1:
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_task_simple, parent, false);
return new SimpleViewHolder(view);
case 2:
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_task_detailed, parent, false);
return new DetailedViewHolder(view);
}
return null;
}
@Override
public void onBindViewHolder(final SimpleViewHolder holder, int position) {
// Set basic information
holder.mItem = mValues.get(position);
holder.mIdView.setText(String.valueOf(holder.mItem.getId()));
holder.mCycleView.setText(String.valueOf(holder.mItem.getCycle()));
holder.mTitleView.setText(holder.mItem.getName());
// Set optional description
if (holder instanceof DetailedViewHolder)
((DetailedViewHolder)holder).mDescriptionView.setText(holder.mItem.getDescription());
// Set task rendering
holder.mTitleView.setTypeface(Typeface.DEFAULT);
holder.mTitleView.setTextColor(Color.BLACK);
// Additional information will not be displayed in Today view
if (mIsToday) return;
// Set alarm if past due date
LocalDate dueDate = holder.mItem.getDueDate();
if(dueDate != null && dueDate.isBefore(LocalDate.now()))
holder.mAlarmView.setImageResource(R.drawable.ic_access_alarm);
int priority = holder.mItem.getPriority();
// Set priority
switch (priority)
{
case 0:
holder.mTitleView.setTextColor(Color.LTGRAY);
break;
case 2:
holder.mTitleView.setTypeface(holder.mTitleView.getTypeface(), Typeface.BOLD);
break;
}
}
@Override
public int getItemCount() {
return mValues.size();
}
@Override
public long getItemId(int position) {
return getItem(position).getId();
}
@Override
public int getItemViewType(int position) {
return viewType;
}
public void setItemViewType(int viewType) {
this.viewType = viewType;
}
public void add(Task item, int position) {
mValues.add(position, item);
notifyItemInserted(position);
}
public void remove(int position) {
mValues.remove(position);
notifyItemRemoved(position);
}
public void update(Task item, int position) {
mValues.set(position, item);
notifyItemChanged(position);
}
public int getCycleCount() {
int count = 0;
for (Task task: mValues) {
count += task.getCycle();
}
return count;
}
public void setItems(List<Task> tasks) {
this.mValues = tasks;
notifyDataSetChanged();
}
public Task getItem(int position) {
return mValues.get(position);
}
class SimpleViewHolder extends RecyclerView.ViewHolder {
final View mView;
final TextView mIdView;
final ImageView mAlarmView;
final TextView mCycleView;
final TextView mTitleView;
Task mItem;
SimpleViewHolder(View view) {
super(view);
mView = view;
mIdView = (TextView) view.findViewById(R.id.task_id);
mAlarmView = (ImageView) view.findViewById(R.id.task_alarm);
mCycleView = (TextView) view.findViewById(R.id.task_cycle);
mTitleView = (TextView) view.findViewById(R.id.task_name);
}
@Override
public String toString() {
return super.toString() + " '" + mTitleView.getText() + "'";
}
}
private class DetailedViewHolder extends SimpleViewHolder {
private final TextView mDescriptionView;
private DetailedViewHolder(View view) {
super(view);
mDescriptionView = (TextView) view.findViewById(R.id.task_description);
}
@Override
public String toString() {
return super.toString() + " '" + mTitleView.getText() + "'";
}
}
}

View File

@@ -0,0 +1,54 @@
package com.wismna.geoffroy.donext.adapters;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.wismna.geoffroy.donext.R;
import com.wismna.geoffroy.donext.dao.Task;
import java.util.List;
/**
* Created by bg45 on 2017-03-22.
* Custom array adapter for the Today Task list view
*/
public class TodayArrayAdapter extends ArrayAdapter<Task> {
public TodayArrayAdapter(@NonNull Context context, @NonNull List<Task> objects) {
super(context, R.layout.list_task_item, objects);
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
//return super.getView(position, convertView, parent);
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_task_item, parent, false);
}
TextView titleView = (TextView) convertView.findViewById(R.id.task_list_item_title);
TextView taskView = (TextView) convertView.findViewById(R.id.task_list_item_tasklist);
LinearLayout layoutView = (LinearLayout) convertView.findViewById(R.id.task_list_item_layout);
Task item = this.getItem(position);
if (item != null) {
titleView.setText(item.getName());
taskView.setText(item.getTaskListName());
if (item.isToday()) {
titleView.setTypeface(titleView.getTypeface(), Typeface.BOLD);
layoutView.setBackgroundColor(Color.parseColor("#B2DFDB"));
} else {
titleView.setTypeface(Typeface.DEFAULT);
layoutView.setBackgroundColor(Color.WHITE);
}
}
return convertView;
}
}

View File

@@ -0,0 +1,125 @@
package com.wismna.geoffroy.donext.dao;
import org.joda.time.LocalDate;
/**
* Created by geoffroy on 15-11-25.
* Data access object class that represents a Task
*/
public class Task {
private long id;
private String name;
private String description;
private int priority;
private int cycle;
private int done;
private int deleted;
private long taskList;
private String taskListName;
private LocalDate dueDate;
private LocalDate todayDate;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String comment) {
this.name = comment;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public int getCycle() {
return cycle;
}
public void setCycle(int cycle) {
this.cycle = cycle;
}
public boolean isDone() {
return done != 0;
}
public void setDone(int done) {
this.done = done;
}
public boolean isDeleted() {
return deleted != 0;
}
public void setDeleted(int deleted) {
this.deleted = deleted;
}
public long getTaskListId() {
return taskList;
}
public void setTaskList(long taskList) {
this.taskList = taskList;
}
public String getTaskListName() {
return taskListName;
}
public void setTaskListName(String taskListName) {
this.taskListName = taskListName;
}
public void setDueDate(String dueDate) {
try {
this.dueDate = LocalDate.parse(dueDate);
}
catch (Exception e){
this.dueDate = null;
}
}
public LocalDate getDueDate() {
return dueDate;
}
public void setTodayDate(String todayDate) {
try {
this.todayDate = LocalDate.parse(todayDate);
}
catch (Exception e){
this.todayDate = null;
}
}
public boolean isToday() {
return todayDate != null && todayDate.isEqual(LocalDate.now());
}
// Will be used by the ArrayAdapter in the ListView
@Override
public String toString() {
return name;
}
}

View File

@@ -0,0 +1,57 @@
package com.wismna.geoffroy.donext.dao;
/**
* Created by geoffroy on 15-11-25.
* Data access object class that represents a Task List
*/
public class TaskList {
private long id;
private String name;
private long taskCount;
private int order;
private Boolean visible;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String comment) {
this.name = comment;
}
public long getTaskCount() {
return taskCount;
}
public void setTaskCount(long taskCount) {
this.taskCount = taskCount;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public void setVisible(int visible) {
this.visible = visible != 0;
}
public Boolean isVisible() {
return visible;
}
@Override
public String toString() {
return name;
}
}

View File

@@ -0,0 +1,93 @@
package com.wismna.geoffroy.donext.database;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Created by geoffroy on 15-11-25.
* Database helper class that contains table and column names as well as handles database creation
*/
class DatabaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 5;
private static final String DATABASE_NAME = "donext.db";
static final String COLUMN_ID = "_id";
static final String COLUMN_ORDER = "displayorder";
static final String TASKLIST_TABLE_NAME = "tasklist";
static final String TASKLIST_COLUMN_NAME = "name";
static final String TASKLIST_COLUMN_TASK_COUNT = "taskcount";
static final String TASKLIST_COLUMN_VISIBLE = "visible";
private static final String TASKLIST_TABLE_CREATE =
"CREATE TABLE " + TASKLIST_TABLE_NAME + " (" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
TASKLIST_COLUMN_NAME + " TEXT NOT NULL, " +
COLUMN_ORDER + " INTEGER, " +
TASKLIST_COLUMN_VISIBLE + " INTEGER DEFAULT 1" +
");";
static final String TASKS_TABLE_NAME = "tasks";
static final String TASKS_COLUMN_NAME = "name";
static final String TASKS_COLUMN_DESC = "description";
static final String TASKS_COLUMN_CYCLE = "cycle";
static final String TASKS_COLUMN_PRIORITY = "priority";
static final String TASKS_COLUMN_DONE = "done";
static final String TASKS_COLUMN_DELETED= "deleted";
static final String TASKS_COLUMN_LIST = "list";
static final String TASKS_COLUMN_DUEDATE = "duedate";
static final String TASKS_COLUMN_TODAYDATE = "todaydate";
private static final String TASKS_TABLE_CREATE =
"CREATE TABLE " + TASKS_TABLE_NAME + " (" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
TASKS_COLUMN_NAME + " TEXT NOT NULL, " +
TASKS_COLUMN_DESC + " TEXT, " +
TASKS_COLUMN_PRIORITY + " INTEGER, " +
TASKS_COLUMN_CYCLE + " INTEGER DEFAULT 0, " +
TASKS_COLUMN_DONE + " INTEGER DEFAULT 0, " +
TASKS_COLUMN_DELETED + " INTEGER DEFAULT 0, " +
COLUMN_ORDER + " INTEGER, " +
TASKS_COLUMN_LIST + " INTEGER NOT NULL " +
"REFERENCES " + TASKLIST_TABLE_NAME + "(" + COLUMN_ID + "), " +
TASKS_COLUMN_DUEDATE + " DATE, " +
TASKS_COLUMN_TODAYDATE + " DATE" +
");";
static final String TASKS_VIEW_TODAY_NAME = "today";
private static final String TASKS_VIEW_TODAY_CREATE =
"CREATE VIEW " + TASKS_VIEW_TODAY_NAME + " AS" +
" SELECT * FROM " + TASKS_TABLE_NAME +
" WHERE " + TASKS_COLUMN_TODAYDATE + " = date('now','localtime')";
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(TASKLIST_TABLE_CREATE);
db.execSQL(TASKS_TABLE_CREATE);
db.execSQL(TASKS_VIEW_TODAY_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Fall-through is intended
switch (oldVersion) {
case 1:
// Add new Order column
db.execSQL("ALTER TABLE " + TASKLIST_TABLE_NAME + " ADD COLUMN " + COLUMN_ORDER + " INTEGER");
case 2:
// Add new Visible column
db.execSQL("ALTER TABLE " + TASKLIST_TABLE_NAME + " ADD COLUMN " + TASKLIST_COLUMN_VISIBLE + " INTEGER DEFAULT 1");
// Add new Due Date column
db.execSQL("ALTER TABLE " + TASKS_TABLE_NAME + " ADD COLUMN " + TASKS_COLUMN_DUEDATE + " DATE");
case 3:
// Add new Today Date column
db.execSQL("ALTER TABLE " + TASKS_TABLE_NAME + " ADD COLUMN " + TASKS_COLUMN_TODAYDATE + " DATE");
// Create the Today view
db.execSQL(TASKS_VIEW_TODAY_CREATE);
case 4:
db.execSQL("DROP VIEW " + TASKS_VIEW_TODAY_NAME);
db.execSQL(TASKS_VIEW_TODAY_CREATE);
}
}
}

View File

@@ -0,0 +1,185 @@
package com.wismna.geoffroy.donext.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import com.wismna.geoffroy.donext.dao.Task;
import org.joda.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
/**
* Created by geoffroy on 15-11-27.
* Data access class that handles Tasks
*/
public class TaskDataAccess implements AutoCloseable {
public enum MODE {
READ,
WRITE
}
private SQLiteDatabase database;
private final DatabaseHelper dbHelper;
private final String[] taskColumns = {
DatabaseHelper.COLUMN_ID, DatabaseHelper.TASKS_COLUMN_NAME,
DatabaseHelper.TASKS_COLUMN_DESC, DatabaseHelper.TASKS_COLUMN_PRIORITY,
DatabaseHelper.TASKS_COLUMN_CYCLE, DatabaseHelper.TASKS_COLUMN_DONE,
DatabaseHelper.TASKS_COLUMN_DELETED, DatabaseHelper.TASKS_COLUMN_LIST,
DatabaseHelper.TASKS_COLUMN_DUEDATE, DatabaseHelper.TASKS_COLUMN_TODAYDATE};
public TaskDataAccess(Context context) {
this(context, MODE.READ);
}
public TaskDataAccess(Context context, MODE writeMode) {
dbHelper = new DatabaseHelper(context);
open(writeMode);
}
private void open(MODE writeMode) throws SQLException {
if (writeMode == MODE.WRITE) database = dbHelper.getWritableDatabase();
else database = dbHelper.getReadableDatabase();
}
public void close() {
dbHelper.close();
}
/** Adds or update a task in the database */
public Task createOrUpdateTask(long id, String name, String description, int priority,
long taskList, String dueDate, boolean isTodayList) {
ContentValues values = new ContentValues();
values.put(DatabaseHelper.TASKS_COLUMN_NAME, name);
values.put(DatabaseHelper.TASKS_COLUMN_DESC, description);
values.put(DatabaseHelper.TASKS_COLUMN_PRIORITY, priority);
values.put(DatabaseHelper.TASKS_COLUMN_LIST, taskList);
values.put(DatabaseHelper.TASKS_COLUMN_DUEDATE, dueDate);
values.put(DatabaseHelper.TASKS_COLUMN_TODAYDATE, isTodayList? LocalDate.now().toString() : "");
long insertId;
if (id == 0)
insertId = database.insert(DatabaseHelper.TASKS_TABLE_NAME, null, values);
else {
database.update(DatabaseHelper.TASKS_TABLE_NAME, values, DatabaseHelper.COLUMN_ID + " == " + id, null);
insertId = id;
}
Cursor cursor = database.query(DatabaseHelper.TASKS_TABLE_NAME,
taskColumns, DatabaseHelper.COLUMN_ID + " = " + insertId, null,
null, null, null);
cursor.moveToFirst();
Task newTask = cursorToTask(cursor);
cursor.close();
return newTask;
}
public void updateTodayTasks(long id, boolean isTodayList){
ContentValues contentValues = new ContentValues();
contentValues.put(DatabaseHelper.TASKS_COLUMN_TODAYDATE, isTodayList? LocalDate.now().toString() : "");
database.update(DatabaseHelper.TASKS_TABLE_NAME, contentValues,
DatabaseHelper.COLUMN_ID + " == " + id, null);
}
public List<Task> getAllTasks() {
Cursor cursor = database.rawQuery("SELECT " +
DatabaseHelper.TASKS_TABLE_NAME + "." + DatabaseHelper.COLUMN_ID + "," +
DatabaseHelper.TASKS_TABLE_NAME + "." + DatabaseHelper.TASKS_COLUMN_NAME + "," +
DatabaseHelper.TASKS_TABLE_NAME + "." + DatabaseHelper.TASKS_COLUMN_TODAYDATE + "," +
DatabaseHelper.TASKLIST_TABLE_NAME + "." + DatabaseHelper.TASKLIST_COLUMN_NAME + " AS tasklistname " +
" FROM " + DatabaseHelper.TASKS_TABLE_NAME +
" LEFT JOIN " + DatabaseHelper.TASKLIST_TABLE_NAME +
" ON " + DatabaseHelper.TASKS_TABLE_NAME + "." + DatabaseHelper.TASKS_COLUMN_LIST +
" = " + DatabaseHelper.TASKLIST_TABLE_NAME + "." + DatabaseHelper.COLUMN_ID +
" WHERE " + DatabaseHelper.TASKS_TABLE_NAME + "." + DatabaseHelper.TASKS_COLUMN_DONE + " = " + 0 +
" AND " + DatabaseHelper.TASKS_TABLE_NAME + "." + DatabaseHelper.TASKS_COLUMN_DELETED + " = " + 0
, null);
List<Task> tasks = new ArrayList<>();
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
Task task = new Task();
task.setId(cursor.getLong(0));
task.setName(cursor.getString(1));
task.setTodayDate(cursor.getString(2));
task.setTaskListName(cursor.getString(3));
tasks.add(task);
cursor.moveToNext();
}
// make sure to close the cursor
cursor.close();
return tasks;
}
public List<Task> getAllTasksFromList(long id, boolean isHistory) {
int history = isHistory ? 1 : 0;
Cursor cursor = database.query(DatabaseHelper.TASKS_TABLE_NAME, taskColumns,
DatabaseHelper.TASKS_COLUMN_LIST + " = " + id +
" AND (" + DatabaseHelper.TASKS_COLUMN_DONE + " = " + history +
(isHistory ? " OR " : " AND ") + DatabaseHelper.TASKS_COLUMN_DELETED + " = " + history + ")",
null, null, null,
DatabaseHelper.TASKS_COLUMN_CYCLE + ", " + DatabaseHelper.COLUMN_ID + " DESC");
return getTasksFromCursor(cursor);
}
public List<Task> getTodayTasks() {
Cursor cursor = database.query(DatabaseHelper.TASKS_VIEW_TODAY_NAME, taskColumns,
DatabaseHelper.TASKS_COLUMN_DONE + " = " + 0 +
" AND " + DatabaseHelper.TASKS_COLUMN_DELETED + " = " + 0,
null, null, null,
DatabaseHelper.TASKS_COLUMN_CYCLE + ", " + DatabaseHelper.COLUMN_ID + " DESC");
return getTasksFromCursor(cursor);
}
public int setDone(long id) {
return update(id, DatabaseHelper.TASKS_COLUMN_DONE, 1);
}
public int increaseCycle(int newCycle, long id) {
return update(id, DatabaseHelper.TASKS_COLUMN_CYCLE, newCycle);
}
public int deleteTask(long id) {
/*database.delete(DatabaseHelper.TASKS_TABLE_NAME,
DatabaseHelper.COLUMN_ID + " = " + taskId, null);*/
return update(id, DatabaseHelper.TASKS_COLUMN_DELETED, 1);
}
private int update(long id, String column, Object value) {
ContentValues contentValues = new ContentValues();
if (value instanceof Integer)
contentValues.put(column, (int) value);
return database.update(DatabaseHelper.TASKS_TABLE_NAME, contentValues, DatabaseHelper.COLUMN_ID + " = " + id, null);
}
private Task cursorToTask(Cursor cursor) {
Task task = new Task();
task.setId(cursor.getLong(0));
task.setName(cursor.getString(1));
task.setDescription(cursor.getString(2));
task.setPriority(cursor.getInt(3));
task.setCycle(cursor.getInt(4));
task.setDone(cursor.getInt(5));
task.setDeleted(cursor.getInt(6));
task.setTaskList(cursor.getLong(7));
task.setDueDate(cursor.getString(8));
task.setTodayDate(cursor.getString(9));
return task;
}
private List<Task> getTasksFromCursor(Cursor cursor) {
List<Task> tasks = new ArrayList<>();
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
Task task = cursorToTask(cursor);
tasks.add(task);
cursor.moveToNext();
}
// make sure to close the cursor
cursor.close();
return tasks;
}
}

View File

@@ -0,0 +1,144 @@
package com.wismna.geoffroy.donext.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import com.wismna.geoffroy.donext.dao.TaskList;
import java.util.ArrayList;
import java.util.List;
/**
* Created by geoffroy on 15-11-25.
* Data access class that handles Task Lists
*/
public class TaskListDataAccess implements AutoCloseable {
public enum MODE {
READ,
WRITE
}
// Database fields
private SQLiteDatabase database;
private final DatabaseHelper dbHelper;
private final String[] taskListColumns =
{DatabaseHelper.COLUMN_ID, DatabaseHelper.TASKLIST_COLUMN_NAME,
DatabaseHelper.COLUMN_ORDER, DatabaseHelper.TASKLIST_COLUMN_VISIBLE};
public TaskListDataAccess(Context context) {
this(context, MODE.READ);
}
public TaskListDataAccess(Context context, MODE writeMode) {
dbHelper = new DatabaseHelper(context);
open(writeMode);
}
public void open(MODE writeMode) throws SQLException {
if (writeMode == MODE.WRITE) database = dbHelper.getWritableDatabase();
else database = dbHelper.getReadableDatabase();
}
public void close() {
dbHelper.close();
}
public TaskList createTaskList(String name, int order) {
ContentValues values = new ContentValues();
values.put(DatabaseHelper.TASKLIST_COLUMN_NAME, name);
values.put(DatabaseHelper.COLUMN_ORDER, order);
values.put(DatabaseHelper.TASKLIST_COLUMN_VISIBLE, 1);
long insertId = database.insert(DatabaseHelper.TASKLIST_TABLE_NAME, null,
values);
Cursor cursor = database.query(DatabaseHelper.TASKLIST_TABLE_NAME,
taskListColumns, DatabaseHelper.COLUMN_ID + " = " + insertId, null,
null, null, null);
cursor.moveToFirst();
TaskList newTaskList = cursorToTaskList(cursor);
cursor.close();
return newTaskList;
}
public void deleteTaskList(long id) {
// Delete all related tasks
database.delete(DatabaseHelper.TASKS_TABLE_NAME, DatabaseHelper.TASKS_COLUMN_LIST
+ " = " + id, null);
// Delete list
database.delete(DatabaseHelper.TASKLIST_TABLE_NAME, DatabaseHelper.COLUMN_ID
+ " = " + id, null);
}
public void updateOrder(long id, int order) {
update(id, DatabaseHelper.COLUMN_ORDER, order);
}
public void updateName(long id, String name) {
update(id, DatabaseHelper.TASKLIST_COLUMN_NAME, name);
}
public TaskList getTaskListByName(String name) {
Cursor cursor = getTaskListByNameCursor(name);
TaskList taskList = null;
if (cursor.getCount() > 0) {
cursor.moveToFirst();
taskList = cursorToTaskList(cursor);
cursor.close();
}
return taskList;
}
public List<TaskList> getAllTaskLists() {
List<TaskList> taskLists = new ArrayList<>();
Cursor cursor = getAllTaskListsCursor();
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
TaskList taskList = cursorToTaskList(cursor);
taskLists.add(taskList);
cursor.moveToNext();
}
// make sure to close the cursor
cursor.close();
return taskLists;
}
private void update(long id, String column, Object value)
{
ContentValues contentValues = new ContentValues();
if (value instanceof String)
contentValues.put(column, (String) value);
if (value instanceof Integer)
contentValues.put(column, (int) value);
database.update(DatabaseHelper.TASKLIST_TABLE_NAME, contentValues, DatabaseHelper.COLUMN_ID + " = " + id, null);
}
private Cursor getTaskListByNameCursor(String name) {
return database.query(true, DatabaseHelper.TASKLIST_TABLE_NAME, taskListColumns,
DatabaseHelper.TASKLIST_COLUMN_NAME + " = '" + name.replace("'", "''") + "'", null, null, null, null, null);
}
private Cursor getAllTaskListsCursor() {
return database.rawQuery("SELECT *," +
" (SELECT COUNT(*) " +
" FROM " + DatabaseHelper.TASKS_TABLE_NAME +
" WHERE " + DatabaseHelper.TASKS_TABLE_NAME + "." + DatabaseHelper.TASKS_COLUMN_LIST + " = " +
DatabaseHelper.TASKLIST_TABLE_NAME + "." + DatabaseHelper.COLUMN_ID + ") AS " + DatabaseHelper.TASKLIST_COLUMN_TASK_COUNT +
" FROM " + DatabaseHelper.TASKLIST_TABLE_NAME +
" WHERE " + DatabaseHelper.TASKLIST_COLUMN_VISIBLE + " = " + 1 +
" ORDER BY " + DatabaseHelper.COLUMN_ORDER + " ASC ",
null);
}
private TaskList cursorToTaskList(Cursor cursor) {
TaskList taskList = new TaskList();
taskList.setId(cursor.getLong(0));
taskList.setName(cursor.getString(1));
taskList.setOrder(cursor.getInt(2));
taskList.setVisible(cursor.getInt(3));
// Get "false" count column if it exists
if (cursor.getColumnCount() == 5)
taskList.setTaskCount(cursor.getLong(4));
return taskList;
}
}

View File

@@ -0,0 +1,87 @@
package com.wismna.geoffroy.donext.fragments;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import com.wismna.geoffroy.donext.R;
public class ConfirmDialogFragment extends DialogFragment {
interface ConfirmDialogListener {
void onConfirmDialogClick(DialogFragment dialog, ButtonEvent event);
}
enum ButtonEvent{
YES,
NO
}
private ConfirmDialogListener confirmDialogListener;
//private String message;
public static ConfirmDialogFragment newInstance(/*String message, */ConfirmDialogListener confirmDialogListener) {
ConfirmDialogFragment fragment = new ConfirmDialogFragment();
//fragment.message = message;
fragment.confirmDialogListener = confirmDialogListener;
fragment.setRetainInstance(true);
return fragment;
}
@Override
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
// Allows refreshing the first item of the adapter
confirmDialogListener.onConfirmDialogClick(this, ButtonEvent.NO);
}
@Override
@NonNull
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
Bundle args = getArguments();
LayoutInflater inflater = getActivity().getLayoutInflater();
// No need for a parent in a Dialog Fragment
@SuppressLint("InflateParams") View view = inflater.inflate(R.layout.fragment_task_confirmation, null);
builder.setView(view).setMessage(args.getString("message"))
.setPositiveButton(args.getInt("button"), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
confirmDialogListener.onConfirmDialogClick(ConfirmDialogFragment.this, ButtonEvent.YES);
}
})
.setNegativeButton(R.string.task_confirmation_no_button, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
ConfirmDialogFragment.this.getDialog().cancel();
}
})
.setOnKeyListener(new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
return keyCode != KeyEvent.KEYCODE_BACK;
}
});
// Create the AlertDialog object and return it
Dialog dialog = builder.create();
dialog.setCanceledOnTouchOutside(true);
return dialog;
}
@Override
public void onDestroyView() {
Dialog dialog = getDialog();
// Stop the dialog from being dismissed on rotation, due to a bug with the compatibility library
// https://code.google.com/p/android/issues/detail?id=17423
if (dialog != null && getRetainInstance()) {
dialog.setDismissMessage(null);
}
super.onDestroyView();
}
}

View File

@@ -0,0 +1,198 @@
package com.wismna.geoffroy.donext.fragments;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
import com.wismna.geoffroy.donext.R;
/**
* Created by wismna on 2017-03-21.
* Sub-class this class to create a dynamic fragment that will act as a Dialog in large layouts and
* a full screen fragment in smaller layouts.
*/
public abstract class DynamicDialogFragment extends DialogFragment {
int mButtonCount = 2;
int mContentLayoutId = 0;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
// This part is only needed on small layouts (large layouts use onCreateDialog)
if (!getShowsDialog()) {
View view = inflater.inflate(R.layout.fragment_dynamic_dialog, container, false);
AppCompatActivity activity = (AppCompatActivity) getActivity();
assert activity != null;
activity.setSupportActionBar(setToolbarTitle(view));
ActionBar actionBar = activity.getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
actionBar.setHomeAsUpIndicator(android.R.drawable.ic_menu_close_clear_cancel);
}
setHasOptionsMenu(true);
insertContentView(view, inflater);
return view;
}
// This basically returns null
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
@NonNull
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Inflate and set the layout for the dialog
LayoutInflater inflater = getActivity().getLayoutInflater();
// As it is a Dialog, the root ViewGroup can be null without issues
@SuppressLint("InflateParams") final View view = inflater.inflate(R.layout.fragment_dynamic_dialog, null);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
Bundle args = getArguments();
// Set the dialog buttons
assert args != null;
// Add action buttons
builder.setView(view)
.setNegativeButton(args.getString("button_negative"), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Send the negative button event back to the host activity
// Canceled creation, nothing to do
//dialog.cancel();
onNegativeButtonClick();
}
});
if (mButtonCount == 2) {
builder.setPositiveButton(args.getString("button_positive"), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
onPositiveButtonClick(view);
}
});
}
if (mButtonCount == 3) {
builder.setNeutralButton(args.getString("button_neutral"), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
onNeutralButtonClick(view);
}
});
}
setToolbarTitle(view);
insertContentView(view, inflater);
return builder.create();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
//super.onCreateOptionsMenu(menu, inflater);
menu.clear();
getActivity().getMenuInflater().inflate(R.menu.menu_dynamic_fragment, menu);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
Bundle args = getArguments();
// Show the neutral button if needed
if (mButtonCount < 3) {
menu.removeItem(R.id.menu_neutral_button);
}
else {
menu.findItem(R.id.menu_neutral_button).setTitle(args.getString("button_neutral"));
}
// Show the positive button if needed
if (mButtonCount < 2) {
menu.removeItem(R.id.menu_positive_button);
}
else {
menu.findItem(R.id.menu_positive_button).setTitle(args.getString("button_positive"));
}
super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Determine which menu item was clicked
int id = item.getItemId();
View view = getView();
// Hide the keyboard if present
if (view != null) {
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
assert imm != null;
imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
}
if (id == R.id.menu_positive_button) {
// Handle positive button click here
onPositiveButtonClick(view);
return true;
}
else if (id == R.id.menu_neutral_button) {
// Handle neutral button click here
onNeutralButtonClick(view);
return true;
}
else if (id == android.R.id.home) {
// Handle negative button click here
onNegativeButtonClick();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onDestroyView() {
Dialog dialog = getDialog();
// Stop the dialog from being dismissed on rotation, due to a bug with the compatibility library
// https://code.google.com/p/android/issues/detail?id=17423
if (dialog != null && getRetainInstance()) {
dialog.setDismissMessage(null);
}
super.onDestroyView();
}
/** Helper function to get a View, without having to worry about the fact that is a Dialog or not*/
protected View findViewById(int id) {
if (getShowsDialog()) return getDialog().findViewById(id);
return getView().findViewById(id);
}
/** Sets the title of the Fragment from the Tag */
private Toolbar setToolbarTitle(View view) {
Toolbar toolbar = view.findViewById(R.id.dialog_toolbar);
toolbar.setTitle(getTag());
return toolbar;
}
/** Inserts the actual contents in the content Frame Layout */
private void insertContentView(View view, LayoutInflater inflater) {
// Ensure that the content view is set
if (mContentLayoutId == 0) return;
// Insert the content view
FrameLayout content = view.findViewById(R.id.dynamic_fragment_content);
content.addView(inflater.inflate(mContentLayoutId, (ViewGroup) view.getParent()));
}
protected abstract void onPositiveButtonClick(View view);
protected abstract void onNeutralButtonClick(View view);
protected abstract void onNegativeButtonClick();
}

View File

@@ -0,0 +1,235 @@
package com.wismna.geoffroy.donext.fragments;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Point;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.wismna.geoffroy.donext.R;
import com.wismna.geoffroy.donext.activities.TaskListActivity;
import com.wismna.geoffroy.donext.adapters.SmartFragmentStatePagerAdapter;
import com.wismna.geoffroy.donext.adapters.TaskRecyclerViewAdapter;
import com.wismna.geoffroy.donext.dao.Task;
import com.wismna.geoffroy.donext.dao.TaskList;
import com.wismna.geoffroy.donext.database.TaskListDataAccess;
import java.util.List;
/**
* Fragment that will handle the main display
*/
public class MainFragment extends Fragment implements TasksFragment.TaskChangedAdapter {
private View mView;
private ViewPager mViewPager;
private SectionsPagerAdapter mSectionsPagerAdapter;
private TabLayout tabLayout;
private List<TaskList> taskLists;
private boolean isHistory = false;
public MainFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param isHistory Will this fragment show the task history?
* @return A new instance of fragment MainFragment.
*/
// TODO: Rename and change types and number of parameters
public static MainFragment newInstance(boolean isHistory) {
MainFragment fragment = new MainFragment();
Bundle args = new Bundle();
args.putBoolean("history", isHistory);
fragment.setArguments(args);
return fragment;
}
public ViewPager getViewPager() {
return mViewPager;
}
public void toggleHistory() {
isHistory = !isHistory;
mSectionsPagerAdapter.notifyDataSetChanged();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
isHistory = getArguments().getBoolean("history");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
mView = inflater.inflate(R.layout.fragment_main, container, false);
AppCompatActivity activity = (AppCompatActivity) getActivity();
Toolbar toolbar = mView.findViewById(R.id.toolbar);
activity.setSupportActionBar(toolbar);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
SharedPreferences sharedPref =
PreferenceManager.getDefaultSharedPreferences(activity);
// Access database to retrieve Tabs
try (TaskListDataAccess taskListDataAccess = new TaskListDataAccess(activity)) {
taskLists = taskListDataAccess.getAllTaskLists();
mSectionsPagerAdapter.notifyDataSetChanged();
}
if (taskLists.size() == 0) {
Intent intent = new Intent(getContext(), TaskListActivity.class);
startActivity(intent);
}
else {
int lastOpenedList = sharedPref.getInt("last_opened_tab", 0);
// Set up the ViewPager with the sections adapter.
mViewPager = mView.findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
// Open last opened tab
mViewPager.setCurrentItem(lastOpenedList);
if (!getResources().getBoolean(R.bool.large_layout)) {
tabLayout = mView.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
// Handles scroll detection (only available for SDK version >=23)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
toggleTabLayoutArrows(tabLayout.getScrollX());
//tabLayout.setScrollIndicators(TabLayout.SCROLL_INDICATOR_LEFT | TabLayout.SCROLL_INDICATOR_RIGHT);
tabLayout.setOnScrollChangeListener(new View.OnScrollChangeListener() {
@Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
toggleTabLayoutArrows(scrollX);
}
});
}
}
else {
ListView listView = mView.findViewById(R.id.list);
//listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, taskLists));
listView.setAdapter(new ArrayAdapter<>(activity, R.layout.list_tasklist_item, taskLists));
//listView.setSelection(lastOpenedList);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mViewPager.setCurrentItem(position);
}
});
}
}
return mView;
}
@Override
public void onPause() {
super.onPause();
// No tabs exist yet, nothing to save
if (mViewPager == null) return;
// Otherwise, save currently opened tab
SharedPreferences sharedPref =
PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt("last_opened_tab", mViewPager.getCurrentItem());
editor.apply();
}
@Override
public void onTaskListChanged(Task task, int tabPosition) {
TaskRecyclerViewAdapter destinationTaskAdapter = getSpecificTabAdapter(tabPosition);
if (destinationTaskAdapter != null) destinationTaskAdapter.add(task, destinationTaskAdapter.getItemCount());
}
private TaskRecyclerViewAdapter getSpecificTabAdapter(int position) {
TasksFragment taskFragment = (TasksFragment) mSectionsPagerAdapter.getRegisteredFragment(position);
if (taskFragment == null) return null;
View view = taskFragment.getView();
if (view == null) return null;
RecyclerView recyclerView = view.findViewById(R.id.task_list_view);
if (recyclerView == null) return null;
return (TaskRecyclerViewAdapter) recyclerView.getAdapter();
}
/** Toggles scrolling arrows visibility */
private void toggleTabLayoutArrows(int scrollX){
// Hide left arrow when scrolled to the left
View leftArrow = mView.findViewById(R.id.left_arrow);
if (leftArrow != null) {
if (scrollX <= 1) leftArrow.setVisibility(View.INVISIBLE);
else leftArrow.setVisibility(View.VISIBLE);
}
// Hide right arrow when scrolled to the right
View rightArrow = mView.findViewById(R.id.right_arrow);
if (rightArrow != null) {
Point size = new Point();
getActivity().getWindowManager().getDefaultDisplay().getSize(size);
if (scrollX == tabLayout.getChildAt(0).getMeasuredWidth() - tabLayout.getMeasuredWidth())
rightArrow.setVisibility(View.INVISIBLE);
else rightArrow.setVisibility(View.VISIBLE);
}
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends SmartFragmentStatePagerAdapter {
SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
TaskList taskList = taskLists.get(position);
return TasksFragment.newTaskListInstance(taskList.getId(), isHistory, MainFragment.this);
}
@Override
public int getCount() {
if (taskLists != null) {
// Show the task lists
return taskLists.size();
}
return 3;
}
@Override
public CharSequence getPageTitle(int position) {
if (taskLists == null) return "N/A";
return taskLists.get(position).getName();
}
public List<TaskList> getAllItems(){
return taskLists;
}
}
}

View File

@@ -0,0 +1,174 @@
package com.wismna.geoffroy.donext.fragments;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;
import com.wismna.geoffroy.donext.R;
import com.wismna.geoffroy.donext.dao.Task;
import com.wismna.geoffroy.donext.dao.TaskList;
import org.joda.time.LocalDate;
import java.util.List;
/**
* Created by bg45 on 2017-03-21.
* This is Task Form dynamic dialog fragment
*/
public class TaskFormDialogFragment extends DynamicDialogFragment {
public Task getTask() {
return task;
}
/** The activity that creates an instance of this dialog fragment must
* implement this interface in order to receive event callbacks.
* Each method passes the DialogFragment in case the host needs to query it. */
interface NewTaskListener {
void onNewTaskDialogPositiveClick(DialogFragment dialog, View dialogView);
void onNewTaskDialogNeutralClick(DialogFragment dialog);
}
private TaskFormDialogFragment.NewTaskListener mListener;
private Task task;
private List<TaskList> taskLists;
public static TaskFormDialogFragment newInstance(Task task, List<TaskList> taskLists, NewTaskListener newTaskListener) {
TaskFormDialogFragment fragment = new TaskFormDialogFragment();
fragment.task = task;
fragment.taskLists = taskLists;
fragment.mListener = newTaskListener;
fragment.setRetainInstance(true);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContentLayoutId = R.layout.content_task_form;
Bundle args = getArguments();
if (args != null) {
mButtonCount = args.getInt("button_count");
}
}
@Override
public void onStart() {
super.onStart();
// Set Task Form specific information at that point because we are sure that the view is
// entirely inflated (with the content fragment)
setTaskValues();
}
@Override
protected void onPositiveButtonClick(View view) {
if (view == null) return;
EditText titleText = view.findViewById(R.id.new_task_name);
// handle confirmation button click hereEditText titleText = (EditText) d.findViewById(R.id.new_task_name);
if (titleText.getText().toString().matches(""))
titleText.setError(getResources().getString(R.string.new_task_name_error));
else {
// Send the positive button event back to the host activity
mListener.onNewTaskDialogPositiveClick(TaskFormDialogFragment.this, view);
dismiss();
}
}
@Override
protected void onNeutralButtonClick(View view) {
mListener.onNewTaskDialogNeutralClick(TaskFormDialogFragment.this);
}
@Override
protected void onNegativeButtonClick() {
dismiss();
}
private void setTaskValues() {
// Populate spinner with task lists
Spinner spinner = (Spinner) findViewById(R.id.new_task_list);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<TaskList> adapter = new ArrayAdapter<>(
getActivity(), android.R.layout.simple_spinner_item, taskLists);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
// Auto set list value to current tab
Bundle args = getArguments();
assert args != null;
int id = args.getInt("list");
spinner.setSelection(id);
CheckBox checkBox = (CheckBox) findViewById(R.id.new_task_today);
TextView todayLabel = (TextView) findViewById(R.id.new_task_today_label);
boolean isTodayActive = args.getBoolean("today");
checkBox.setVisibility(isTodayActive ? View.VISIBLE : View.GONE);
todayLabel.setVisibility(isTodayActive ? View.VISIBLE : View.GONE);
// Get date picker
final DatePicker dueDatePicker = (DatePicker) findViewById(R.id.new_task_due_date);
// Handle due date spinner depending on check box
CheckBox setDueDate = (CheckBox) findViewById(R.id.new_task_due_date_set);
setDueDate.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
dueDatePicker.setVisibility(isChecked ? View.VISIBLE : View.GONE);
}
});
// Handle priority changes
final TextView tooltip = (TextView) findViewById(R.id.new_task_priority_tooltip);
SeekBar seekBar = (SeekBar) findViewById(R.id.new_task_priority);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
tooltip.setText(getResources().getStringArray(R.array.task_priority)[progress]);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
tooltip.setVisibility(View.VISIBLE);
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
tooltip.setVisibility(View.GONE);
}
});
tooltip.setText(getResources().getStringArray(R.array.task_priority)[seekBar.getProgress()]);
// Set other properties if they exist
if (task != null) {
EditText titleText = (EditText) findViewById(R.id.new_task_name);
titleText.setText(task.getName());
EditText descText = (EditText) findViewById(R.id.new_task_description);
descText.setText(task.getDescription());
seekBar.setProgress(task.getPriority());
// Set Due Date
LocalDate dueDate = task.getDueDate();
if (dueDate != null) {
setDueDate.setChecked(true);
dueDatePicker.updateDate(dueDate.getYear(), dueDate.getMonthOfYear() - 1, dueDate.getDayOfMonth());
}
checkBox.setChecked(task.isToday());
}
else {
// Disallow past dates on new tasks
dueDatePicker.setMinDate(LocalDate.now().toDate().getTime());
}
}
}

View File

@@ -0,0 +1,253 @@
package com.wismna.geoffroy.donext.fragments;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.DialogFragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import com.wismna.geoffroy.donext.R;
import com.wismna.geoffroy.donext.adapters.TaskListRecyclerViewAdapter;
import com.wismna.geoffroy.donext.dao.TaskList;
import com.wismna.geoffroy.donext.database.TaskListDataAccess;
import com.wismna.geoffroy.donext.helpers.TaskListTouchHelper;
import java.util.List;
/**
* A fragment representing a list of Items.
*/
public class TaskListsFragment extends DynamicDialogFragment implements
TaskListRecyclerViewAdapter.TaskListRecyclerViewAdapterListener,
ConfirmDialogFragment.ConfirmDialogListener {
private TaskListRecyclerViewAdapter taskListRecyclerViewAdapter;
private TaskListDataAccess taskListDataAccess;
//private View mView;
private ItemTouchHelper mItemTouchHelper;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public TaskListsFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
mButtonCount = args.getInt("button_count");
}
mContentLayoutId = R.layout.fragment_tasklists;
taskListDataAccess = new TaskListDataAccess(getContext(), TaskListDataAccess.MODE.WRITE);
new GetTaskListsTask().execute(taskListDataAccess);
}
/*@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.fragment_tasklists, container, false);
Button createTaskListButton = mView.findViewById(R.id.new_task_list_button);
createTaskListButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EditText editText = mView.findViewById(R.id.new_task_list_name);
String text = editText.getText().toString();
if (text.matches("")) {
editText.setError(getResources().getString(R.string.task_list_new_list_error));
return;
}
int position = taskListRecyclerViewAdapter.getItemCount();
TaskList taskList = taskListDataAccess.createTaskList(text, position);
taskListRecyclerViewAdapter.add(taskList, position);
editText.setText("");
toggleVisibleCreateNewTaskListLayout(mView);
}
});
return mView;
}*/
@Override
public void onStart() {
super.onStart();
Button createTaskListButton = (Button) findViewById(R.id.new_task_list_button);
createTaskListButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EditText editText = (EditText) findViewById(R.id.new_task_list_name);
String text = editText.getText().toString();
if (text.matches("")) {
editText.setError(getResources().getString(R.string.task_list_new_list_error));
return;
}
int position = taskListRecyclerViewAdapter.getItemCount();
TaskList taskList = taskListDataAccess.createTaskList(text, position);
taskListRecyclerViewAdapter.add(taskList, position);
editText.setText("");
toggleVisibleCreateNewTaskListLayout();
}
});
}
@Override
protected void onPositiveButtonClick(View view) {
}
@Override
protected void onNeutralButtonClick(View view) {
}
@Override
protected void onNegativeButtonClick() {
}
@Override
public void onPause() {
clearFocus();
super.onPause();
taskListDataAccess.close();
}
@Override
public void onResume() {
super.onResume();
clearFocus();
taskListDataAccess.open(TaskListDataAccess.MODE.WRITE);
}
private void toggleVisibleCreateNewTaskListLayout() {
LinearLayout layout = (LinearLayout) findViewById(R.id.new_task_list_layout);
int taskListCount = taskListRecyclerViewAdapter.getItemCount();
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
String maxTaskListsString = sharedPref.getString("pref_conf_max_lists", "5");
int maxTaskLists = Integer.valueOf(maxTaskListsString);
if (taskListCount >= maxTaskLists) layout.setVisibility(View.GONE);
else layout.setVisibility(View.VISIBLE);
clearFocus();
}
@Override
public void onEditTextLoseFocus(TaskList taskList) {
taskListDataAccess.updateName(taskList.getId(), taskList.getName());
}
@Override
public void onClickDeleteButton(int position, long id) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
if(sharedPref.getBoolean("pref_conf_tasklist_del", true)) {
String title = getResources().getString(R.string.task_list_confirmation_delete);
ConfirmDialogFragment confirmDialogFragment =
ConfirmDialogFragment.newInstance(this);
Bundle args = new Bundle();
args.putString("message", title);
args.putInt("button", R.string.task_confirmation_delete_button);
args.putInt("ItemPosition", position);
args.putLong("ItemId", id);
confirmDialogFragment.setArguments(args);
confirmDialogFragment.show(getFragmentManager(), title);
}
else deleteTaskList(position, id);
}
@Override
public void onConfirmDialogClick(DialogFragment dialog, ConfirmDialogFragment.ButtonEvent event) {
// Handle never ask again checkbox
CheckBox neverAskAgainCheckBox = dialog.getDialog().findViewById(R.id.task_confirmation_never);
if (neverAskAgainCheckBox.isChecked()) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean("pref_conf_tasklist_del", false);
editor.apply();
}
if (event == ConfirmDialogFragment.ButtonEvent.NO) return;
Bundle args = dialog.getArguments();
assert args != null;
deleteTaskList(args.getInt("ItemPosition"), args.getLong("ItemId"));
}
@Override
public void onItemMove(long fromTaskId, long toTaskId, int fromPosition, int toPosition) {
taskListDataAccess.updateOrder(fromTaskId, toPosition);
taskListDataAccess.updateOrder(toTaskId, fromPosition);
}
@Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
mItemTouchHelper.startDrag(viewHolder);
}
private void deleteTaskList(int position, long id)
{
taskListRecyclerViewAdapter.remove(position);
taskListDataAccess.deleteTaskList(id);
toggleVisibleCreateNewTaskListLayout();
}
/** Helper method to clear focus by giving it to the parent layout */
private void clearFocus() {
View view = getView();
if (view != null) {
view.requestFocus();
// Hide keyboard
InputMethodManager inputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
private class GetTaskListsTask extends AsyncTask<TaskListDataAccess, Void, List<TaskList>> {
@Override
protected List<TaskList> doInBackground(TaskListDataAccess... params) {
TaskListDataAccess taskListDataAccess = params[0];
return taskListDataAccess.getAllTaskLists();
}
@Override
protected void onPostExecute(List<TaskList> taskLists) {
super.onPostExecute(taskLists);
taskListRecyclerViewAdapter =
new TaskListRecyclerViewAdapter(taskLists, TaskListsFragment.this);
// Set the adapter
Context context = getContext();
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.task_lists_view);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.setAdapter(taskListRecyclerViewAdapter);
// Set the Touch Helper
ItemTouchHelper.Callback callback = new TaskListTouchHelper(taskListRecyclerViewAdapter);
mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(recyclerView);
toggleVisibleCreateNewTaskListLayout();
}
}
}

View File

@@ -0,0 +1,477 @@
package com.wismna.geoffroy.donext.fragments;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.design.widget.Snackbar;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.CheckBox;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;
import com.wismna.geoffroy.donext.R;
import com.wismna.geoffroy.donext.adapters.TaskRecyclerViewAdapter;
import com.wismna.geoffroy.donext.dao.Task;
import com.wismna.geoffroy.donext.dao.TaskList;
import com.wismna.geoffroy.donext.database.TaskDataAccess;
import com.wismna.geoffroy.donext.database.TaskListDataAccess;
import com.wismna.geoffroy.donext.helpers.TaskTouchHelper;
import com.wismna.geoffroy.donext.listeners.RecyclerItemClickListener;
import com.wismna.geoffroy.donext.widgets.DividerItemDecoration;
import com.wismna.geoffroy.donext.widgets.NoScrollingLayoutManager;
import org.joda.time.LocalDate;
import java.util.List;
/**
* A fragment representing a list of Items.
*/
public class TasksFragment extends Fragment implements
TaskFormDialogFragment.NewTaskListener,
ConfirmDialogFragment.ConfirmDialogListener,
TaskTouchHelper.TaskTouchHelperAdapter{
interface TaskChangedAdapter {
void onTaskListChanged(Task task, int tabPosition);
}
private static final String TASK_LIST_ID = "task_list_id";
private long taskListId = -1;
private boolean isTodayView = true;
private boolean isHistory = false;
private TaskRecyclerViewAdapter taskRecyclerViewAdapter;
private View view;
private RecyclerView recyclerView;
private TaskChangedAdapter mAdapter;
private Snackbar snackbar;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public TasksFragment() {
}
public static TasksFragment newTaskListInstance(long taskListId, boolean isHistory,
TaskChangedAdapter taskChangedAdapter) {
TasksFragment fragment = new TasksFragment();
Bundle args = new Bundle();
args.putLong(TASK_LIST_ID, taskListId);
args.putBoolean("history", isHistory);
fragment.setArguments(args);
fragment.mAdapter = taskChangedAdapter;
fragment.isTodayView = false;
fragment.setRetainInstance(true);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
taskListId = getArguments().getLong(TASK_LIST_ID);
isHistory = getArguments().getBoolean("history");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_tasks, container, false);
final Context context = view.getContext();
// Set the Recycler view
recyclerView = view.findViewById(R.id.task_list_view);
recyclerView.setLayoutManager(new NoScrollingLayoutManager(context));
// Set RecyclerView Adapter
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
// Get all tasks
try (TaskDataAccess taskDataAccess = new TaskDataAccess(view.getContext())) {
taskRecyclerViewAdapter = new TaskRecyclerViewAdapter(
isTodayView? taskDataAccess.getTodayTasks() : taskDataAccess.getAllTasksFromList(taskListId, isHistory),
Integer.valueOf(sharedPref.getString("pref_conf_task_layout", "1")), isTodayView);
}
recyclerView.setAdapter(taskRecyclerViewAdapter);
// Set ItemTouch helper in RecyclerView to handle swipe move on elements
final Resources resources = getResources();
ItemTouchHelper.Callback callback = new TaskTouchHelper(this,
ContextCompat.getColor(context, R.color.colorPrimary),
ContextCompat.getColor(context, R.color.colorAccent));
ItemTouchHelper helper = new ItemTouchHelper(callback);
helper.attachToRecyclerView(recyclerView);
// Implements touch listener to add click detection
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
boolean isLargeLayout = resources.getBoolean(R.bool.large_layout);
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
Bundle args = new Bundle();
args.putInt("position", position);
args.putBoolean("today", sharedPref.getBoolean("pref_conf_today_enable", false));
args.putBoolean("neutral", true);
args.putString("button_positive", getString(R.string.new_task_save));
args.putString("button_negative", getString(R.string.new_task_cancel));
args.putString("button_neutral", getString(R.string.new_task_delete));
// Set current tab value to new task dialog
ViewPager viewPager = getActivity().findViewById(R.id.container);
List<TaskList> taskLists;
Task task = taskRecyclerViewAdapter.getItem(position);
if (viewPager != null) {
taskLists = ((MainFragment.SectionsPagerAdapter) viewPager.getAdapter()).getAllItems();
args.putInt("list", viewPager.getCurrentItem());
}
else {
try (TaskListDataAccess taskListDataAccess = new TaskListDataAccess(getActivity())) {
taskLists = taskListDataAccess.getAllTaskLists();
}
for (TaskList taskList :
taskLists) {
if (taskList.getId() == task.getTaskListId()) {
args.putInt("list", taskLists.indexOf(taskList));
break;
}
}
}
FragmentManager manager = getFragmentManager();
TaskFormDialogFragment taskDialogFragment = TaskFormDialogFragment.newInstance(
task, taskLists, TasksFragment.this);
taskDialogFragment.setArguments(args);
// Open the fragment as a dialog or as full-screen depending on screen size
String title = getString(R.string.action_edit_task);
if (isLargeLayout) {
taskDialogFragment.show(manager, title);
}
else {
// The device is smaller, so show the fragment fullscreen
FragmentTransaction transaction = manager.beginTransaction();
// For a little polish, specify a transition animation
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// To make it fullscreen, use the 'content' root view as the container
// for the fragment, which is always the root view for the activity
transaction.add(android.R.id.content, taskDialogFragment, title)
.addToBackStack(null).commit();
}
}
})
);
// Handle updating total counts in a listener to be sure that the layout is available
recyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
// isAdded is tested to prevent an IllegalStateException when fast switching between tabs
if (!isAdded()) return true;
Resources resources = getResources();
// Update total cycle count
int totalCycles = taskRecyclerViewAdapter.getCycleCount();
TextView totalCyclesView = view.findViewById(R.id.total_task_cycles);
if (totalCycles != 0)
totalCyclesView.setText(resources.getQuantityString(R.plurals.task_total_cycles, totalCycles, totalCycles));
else totalCyclesView.setText("");
// Update total tasks
int totalTasks = taskRecyclerViewAdapter.getItemCount();
TextView totalTasksView = view.findViewById(R.id.total_task_count);
View noMoreTasks = view.findViewById(R.id.no_more_tasks);
if (totalTasks == 0) {
noMoreTasks.setVisibility(View.VISIBLE);
totalTasksView.setVisibility(View.GONE);
}
else {
noMoreTasks.setVisibility(View.GONE);
totalTasksView.setVisibility(View.VISIBLE);
totalTasksView.setText(resources.getQuantityString(R.plurals.task_total, totalTasks, totalTasks));
}
// Update remaining tasks
TextView remainingTasksView = view.findViewById(R.id.remaining_task_count);
NoScrollingLayoutManager layoutManager = (NoScrollingLayoutManager) recyclerView.getLayoutManager();
int remainingTaskCount = totalTasks - layoutManager.findLastVisibleItemPosition() - 1;
if (remainingTaskCount == 0) remainingTasksView.setText("");
else remainingTasksView.setText(resources.getQuantityString(R.plurals.task_remaining, remainingTaskCount, remainingTaskCount));
//recyclerView.getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
});
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity()));
return view;
}
@Override
public void onPause() {
if (snackbar != null) snackbar.dismiss();
super.onPause();
}
@Override
public void onConfirmDialogClick(DialogFragment dialog, ConfirmDialogFragment.ButtonEvent event) {
Bundle args = dialog.getArguments();
int itemPosition = args.getInt("ItemPosition");
int direction = args.getInt("Direction");
// Handle never ask again checkbox
CheckBox neverAskAgainCheckBox = dialog.getDialog().findViewById(R.id.task_confirmation_never);
if (neverAskAgainCheckBox.isChecked()) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = sharedPref.edit();
// Set system settings
switch (direction) {
case ItemTouchHelper.LEFT:
editor.putBoolean("pref_conf_done", false);
break;
case ItemTouchHelper.RIGHT:
editor.putBoolean("pref_conf_next", false);
break;
case -1:
editor.putBoolean("pref_conf_del", false);
break;
}
editor.apply();
}
if (event == ConfirmDialogFragment.ButtonEvent.YES) {
PerformTaskAction(itemPosition, direction);
}
else if(event == ConfirmDialogFragment.ButtonEvent.NO) {
taskRecyclerViewAdapter.notifyItemChanged(itemPosition);
}
}
@Override
public void onNewTaskDialogPositiveClick(DialogFragment dialog, View dialogView) {
// Get the dialog fragment
if (dialogView == null) return;
long id = 0;
Task task = ((TaskFormDialogFragment)dialog).getTask();
if (task != null) id = task.getId();
// Get the controls
Spinner listSpinner = dialogView.findViewById(R.id.new_task_list);
EditText nameText = dialogView.findViewById(R.id.new_task_name);
EditText descText = dialogView.findViewById(R.id.new_task_description);
SeekBar seekBar = dialogView.findViewById(R.id.new_task_priority);
CheckBox setDueDate = dialogView.findViewById(R.id.new_task_due_date_set);
DatePicker dueDatePicker = dialogView.findViewById(R.id.new_task_due_date);
TaskList taskList = (TaskList) listSpinner.getSelectedItem();
CheckBox todayList = dialogView.findViewById(R.id.new_task_today);
boolean isToday = todayList.isChecked();
// Add the task to the database
try (TaskDataAccess taskDataAccess = new TaskDataAccess(view.getContext(), TaskDataAccess.MODE.WRITE)) {
Task newTask = taskDataAccess.createOrUpdateTask(id,
nameText.getText().toString(),
descText.getText().toString(),
seekBar.getProgress(),
taskList.getId(),
setDueDate.isChecked() ?
new LocalDate(dueDatePicker.getYear(),
dueDatePicker.getMonth() + 1,
dueDatePicker.getDayOfMonth()).toString()
: "",
isToday);
Bundle args = dialog.getArguments();
// Should never happen because we will have to be on this tab to open the dialog
if (taskRecyclerViewAdapter == null) return;
// Add the task
if (task == null) {
// If the new task is added to another task list, update the tab
if (mAdapter != null && taskListId != taskList.getId()) {
mAdapter.onTaskListChanged(newTask, listSpinner.getSelectedItemPosition());
}
// Otherwise add it to the current one
else {
taskRecyclerViewAdapter.add(newTask, 0);
recyclerView.scrollToPosition(0);
}
}
// Update the task
else {
int position = args.getInt("position");
// Check if task list was changed
if ((isTodayView && !isToday) || (!isTodayView && task.getTaskListId() != taskList.getId()))
{
// Remove item from current tab
taskRecyclerViewAdapter.remove(position);
// Add it to the corresponding tab provided it is already instantiated
if (mAdapter != null) mAdapter.onTaskListChanged(newTask, listSpinner.getSelectedItemPosition());
} else {
taskRecyclerViewAdapter.update(newTask, position);
}
}
}
}
@Override
public void onNewTaskDialogNeutralClick(DialogFragment dialog) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
boolean showDialog = sharedPref.getBoolean("pref_conf_del", true);
Bundle args = dialog.getArguments();
// Delete task from Adapter
final int itemPosition = args.getInt("position");
if (showDialog) {
String title = getResources().getString(R.string.task_confirmation_delete_text);
ConfirmDialogFragment confirmDialogFragment =
ConfirmDialogFragment.newInstance(this);
Bundle confirmArgs = new Bundle();
confirmArgs.putString("message", title);
confirmArgs.putInt("button", R.string.task_confirmation_delete_button);
confirmArgs.putInt("ItemPosition", itemPosition);
confirmArgs.putInt("Direction", -1);
confirmDialogFragment.setArguments(confirmArgs);
confirmDialogFragment.show(getFragmentManager(), title);
}
else {
PerformTaskAction(itemPosition, -1);
}
}
@Override
public void onItemSwiped(int itemPosition, int direction) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
String title = "";
boolean showDialog = false;
int buttonLabel = -1;
switch (direction)
{
// Mark item as Done
case ItemTouchHelper.LEFT:
title = getResources().getString(R.string.task_confirmation_done_text);
showDialog = sharedPref.getBoolean("pref_conf_done", true);
buttonLabel = R.string.task_confirmation_done_button;
break;
// Increase task cycle count
case ItemTouchHelper.RIGHT:
title = getResources().getString(R.string.task_confirmation_next_text);
showDialog = sharedPref.getBoolean("pref_conf_next", true);
buttonLabel = R.string.task_confirmation_next_button;
break;
}
if (showDialog) {
ConfirmDialogFragment confirmDialogFragment =
ConfirmDialogFragment.newInstance(this);
Bundle args = new Bundle();
args.putString("message", title);
args.putInt("button", buttonLabel);
args.putInt("ItemPosition", itemPosition);
args.putInt("Direction", direction);
confirmDialogFragment.setArguments(args);
confirmDialogFragment.show(getFragmentManager(), title);
}
else PerformTaskAction(itemPosition, direction);
}
/** Performs an action on a task: done, next or delete */
private void PerformTaskAction(final int itemPosition, final int direction) {
final long itemId = taskRecyclerViewAdapter.getItemId(itemPosition);
final Task task = taskRecyclerViewAdapter.getItem(itemPosition);
String action = "";
Resources resources = getResources();
taskRecyclerViewAdapter.remove(itemPosition);
switch (direction)
{
// Mark item as Done
case ItemTouchHelper.LEFT:
action = resources.getString(R.string.snackabar_action_done);
break;
// Increase task cycle count
case ItemTouchHelper.RIGHT:
action = resources.getString(R.string.snackabar_action_next);
task.setCycle(task.getCycle() + 1);
taskRecyclerViewAdapter.add(task, taskRecyclerViewAdapter.getItemCount());
break;
case -1:
FragmentManager manager = getFragmentManager();
DialogFragment dialog = (DialogFragment) manager.findFragmentByTag(getString(R.string.action_edit_task));
if (dialog != null) dialog.dismiss();
action = resources.getString(R.string.snackabar_action_deleted);
break;
}
// Setup the snack bar
snackbar = Snackbar.make(view, resources.getString(R.string.snackabar_label, action), Snackbar.LENGTH_LONG)
.setAction(resources.getString(R.string.snackabar_button), new View.OnClickListener() {
@Override
public void onClick(View v) {
// Undo adapter changes
switch (direction) {
// Nothing special to do for done
case ItemTouchHelper.LEFT:
break;
// Remove the last item
case ItemTouchHelper.RIGHT:
taskRecyclerViewAdapter.remove(taskRecyclerViewAdapter.getItemCount() - 1);
task.setCycle(task.getCycle() - 1);
break;
// Nothing special to do for delete
case -1:
break;
}
// Reset the first item
taskRecyclerViewAdapter.add(task, itemPosition);
recyclerView.scrollToPosition(0);
}
});
snackbar.addCallback(new Snackbar.Callback() {
@Override
public void onDismissed(Snackbar snackbar, int event) {
super.onDismissed(snackbar, event);
// When clicked on undo, do not write to DB
if (event == DISMISS_EVENT_ACTION) return;
// Commit the changes to DB
try (TaskDataAccess taskDataAccess = new TaskDataAccess(view.getContext(), TaskDataAccess.MODE.WRITE)) {
switch (direction) {
// Mark item as Done
case ItemTouchHelper.LEFT:
taskDataAccess.setDone(itemId);
break;
// Increase task cycle count
case ItemTouchHelper.RIGHT:
taskDataAccess.increaseCycle(task.getCycle(), itemId);
break;
case -1:
// Delete the task
taskDataAccess.deleteTask(itemId);
}
}
}
}).show();
}
}

View File

@@ -0,0 +1,146 @@
package com.wismna.geoffroy.donext.fragments;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import com.wismna.geoffroy.donext.R;
import com.wismna.geoffroy.donext.adapters.TodayArrayAdapter;
import com.wismna.geoffroy.donext.dao.Task;
import com.wismna.geoffroy.donext.database.TaskDataAccess;
import org.joda.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
/**
* Created by bg45 on 2017-03-21.
* This is the Today Form dynamic dialog fragment
*/
public class TodayFormDialogFragment extends DynamicDialogFragment {
/** The activity that creates an instance of this dialog fragment must
* implement this interface in order to receive event callbacks.
* Each method passes the DialogFragment in case the host needs to query it. */
public interface TodayTaskListener {
void onTodayTaskDialogPositiveClick(View dialogView);
void onTodayTasksUpdated();
}
private TodayFormDialogFragment.TodayTaskListener mListener;
private final List<Task> mUpdatedTasks = new ArrayList<>();
public static TodayFormDialogFragment newInstance(TodayTaskListener todayTaskListener) {
TodayFormDialogFragment fragment = new TodayFormDialogFragment();
fragment.mListener = todayTaskListener;
fragment.setRetainInstance(true);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContentLayoutId = R.layout.content_today_form;
// Load the tasks asynchronously
new LoadTasks().execute(getActivity());
}
private void setLayoutValues(List<Task> tasks) {
EditText editText = (EditText) findViewById(R.id.today_search);
final ListView listView = (ListView) findViewById(R.id.today_tasks);
final TodayArrayAdapter adapter = new TodayArrayAdapter(getActivity(), tasks);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Set Today date for the task
Task task = adapter.getItem(position);
if (task == null) return;
task.setTodayDate(task.isToday() ? "" : LocalDate.now().toString());
// Maintain a list of actually updated tasks to commit to DB
if (!mUpdatedTasks.contains(task)) mUpdatedTasks.add(task);
else mUpdatedTasks.remove(task);
// Refresh the view
adapter.notifyDataSetChanged();
}
});
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
adapter.getFilter().filter(s);
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
@Override
protected void onPositiveButtonClick(View view) {
mListener.onTodayTaskDialogPositiveClick(view);
// Only commit the updated tasks to DB
new UpdateTasks().execute(mUpdatedTasks.toArray(new Task[mUpdatedTasks.size()]));
dismiss();
}
@Override
protected void onNeutralButtonClick(View view) {
}
@Override
protected void onNegativeButtonClick() {
dismiss();
}
private class LoadTasks extends AsyncTask<Context, Void, List<Task>> {
@Override
protected List<Task> doInBackground(Context... params) {
try(TaskDataAccess taskDataAccess = new TaskDataAccess(params[0])) {
return taskDataAccess.getAllTasks();
}
}
@Override
protected void onPostExecute(List<Task> tasks) {
super.onPostExecute(tasks);
setLayoutValues(tasks);
}
}
private class UpdateTasks extends AsyncTask<Task, Void, Integer> {
@Override
protected Integer doInBackground(Task... params) {
int elementsUpdated = 0;
try (TaskDataAccess taskDataAccess = new TaskDataAccess(getActivity(), TaskDataAccess.MODE.WRITE)) {
for (Task task :
params) {
taskDataAccess.updateTodayTasks(task.getId(), task.isToday());
elementsUpdated++;
}
}
return elementsUpdated;
}
@Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
mListener.onTodayTasksUpdated();
}
}
}

View File

@@ -0,0 +1,56 @@
package com.wismna.geoffroy.donext.helpers;
import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
/**
* Created by geoffroy on 15-12-30.
* Helper class that handles all drags events on a TaskList
*/
public class TaskListTouchHelper extends ItemTouchHelper.SimpleCallback {
public interface TaskListTouchHelperAdapter {
boolean onItemMove(int fromPosition, int toPosition);
}
private final TaskListTouchHelperAdapter mAdapter;
public TaskListTouchHelper(TaskListTouchHelperAdapter adapter) {
super(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0);
mAdapter = adapter;
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
// No swipe moves
}
@Override
public boolean isLongPressDragEnabled() {
return false;
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE)
{
viewHolder.itemView.setBackgroundColor(Color.LTGRAY);
}
super.onSelectedChanged(viewHolder, actionState);
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setAlpha(1.0f);
viewHolder.itemView.setBackgroundColor(0);
}
}

View File

@@ -0,0 +1,106 @@
package com.wismna.geoffroy.donext.helpers;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.view.View;
import com.wismna.geoffroy.donext.R;
/**
* Created by geoffroy on 15-12-04.
* Helper class that handles all swipe events on a Task
*/
public class TaskTouchHelper extends ItemTouchHelper.SimpleCallback {
public interface TaskTouchHelperAdapter {
void onItemSwiped(int position, int direction);
}
private final TaskTouchHelperAdapter mAdapter;
private int colorRight;
private int colorLeft;
public TaskTouchHelper(TaskTouchHelperAdapter adapter, int colorRight, int colorLeft){
// No drag moves, no swipes (except for 1st element, see getSwipeDirs method)
super(0, 0);
this.colorRight = colorRight;
this.colorLeft = colorLeft;
this.mAdapter = adapter;
}
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
// Allow both directions swiping on first item, only left on the others
if (viewHolder.getAdapterPosition() == 0)
return ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
else return super.getSwipeDirs(recyclerView, viewHolder);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
mAdapter.onItemSwiped(viewHolder.getAdapterPosition(), direction);
}
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
float dX, float dY, int actionState, boolean isCurrentlyActive) {
// Get RecyclerView item from the ViewHolder
View itemView = viewHolder.itemView;
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
if (dX > 0) {
Rect rect = new Rect(itemView.getLeft(), itemView.getTop(), (int) dX,
itemView.getBottom());
setBackground(c, itemView, rect, dX, dY,
colorLeft, R.string.task_confirmation_next_button);
} else {
// Draw Rect with varying left side, equal to the item's right side plus negative displacement dX
Rect rect = new Rect(itemView.getRight() + (int)dX, itemView.getTop(),
itemView.getRight(), itemView.getBottom());
setBackground(c, itemView, rect, dX, dY,
colorRight, R.string.task_confirmation_done_button);
}
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
private void setBackground(Canvas c, View itemView,
Rect rect, float dX, float dY, int color, int textId) {
TextPaint textPaint = new TextPaint();
textPaint.setAntiAlias(true);
textPaint.setTextSize(25 * itemView.getResources().getDisplayMetrics().density);
textPaint.setColor(Color.WHITE);
int heightOffset = itemView.getHeight() / 2 - (int)textPaint.getTextSize() / 2;
int widthOffset = 30;
Paint background = new Paint();
// Set your color for negative displacement
background.setColor(color);
// Draw Rect with varying left side, equal to the item's right side plus negative displacement dX
c.drawRect(rect, background);
// Draw text in the rectangle
String text = itemView.getResources().getString(textId).toUpperCase();
int width = (int) textPaint.measureText(text);
float textXCoordinate;
if (dX > 0) textXCoordinate = rect.left + widthOffset;
else textXCoordinate = rect.right - width - widthOffset;
c.translate(textXCoordinate, dY + heightOffset);
StaticLayout staticLayout = new StaticLayout(text, textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0, false);
staticLayout.draw(c);
}
}

View File

@@ -0,0 +1,52 @@
package com.wismna.geoffroy.donext.listeners;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by geoffroy on 15-12-02.
* Listener class on RecyclerView to intercept touch events
*/
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private final OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
private final GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
View childView = view.findChildViewUnder(e.getX(), e.getY());
//int childId = view.getChildAdapterPosition(childView);
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
return true;
}
return false;
}
@Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}

View File

@@ -0,0 +1,54 @@
package com.wismna.geoffroy.donext.widgets;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.view.View;
/**
* Created by geoffroy on 16-01-11.
* Displays dividers between RecyclerView items
*/
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
private final Drawable mDivider;
/**
* Default divider will be used
*/
public DividerItemDecoration(Context context) {
final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS);
mDivider = styledAttributes.getDrawable(0);
styledAttributes.recycle();
}
/**
* Custom divider will be used
*/
/*public DividerItemDecoration(Context context, int resId) {
mDivider = ContextCompat.getDrawable(context, resId);
}*/
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int top = child.getBottom() + params.bottomMargin;
int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
}

View File

@@ -0,0 +1,20 @@
package com.wismna.geoffroy.donext.widgets;
import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
/**
* Created by geoffroy on 15-12-21.
* Custom Layout Manager that disables vertical scrolling for the RecyclerView
*/
public class NoScrollingLayoutManager extends LinearLayoutManager {
public NoScrollingLayoutManager(Context context) {
super(context);
}
@Override
public boolean canScrollVertically() {
return false;
}
}

View File

@@ -0,0 +1,33 @@
package com.wismna.geoffroy.donext.widgets;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
* Created by geoffroy on 15-12-04.
* Custom ViewPager to forbid vertical swiping between tabs
*/
public class NonSwipeableViewPager extends ViewPager {
public NonSwipeableViewPager(Context context) {
super(context);
}
public NonSwipeableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 961 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 620 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 B

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/holo_red_light" android:state_selected="true" />
<item android:drawable="@android:color/holo_red_light" android:state_pressed="true" />
<item android:drawable="@android:color/white" android:state_selected="false" />
</selector>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/background_light" />
</selector>

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.wismna.geoffroy.donext.fragments.MainFragment">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<include layout="@layout/toolbar" android:id="@+id/toolbar" />
</android.support.design.widget.AppBarLayout>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize">
<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/left_guideline"
app:layout_constraintGuide_percent="0"
android:orientation="vertical"/>
<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/center_guideline"
app:layout_constraintGuide_percent=".20"
android:orientation="vertical"/>
<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/right_guideline"
app:layout_constraintGuide_percent="1"
android:orientation="vertical"/>
<android.widget.ListView
android:id="@+id/list"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:choiceMode="singleChoice"
android:listSelector="@drawable/tasklist_select"
app:layout_constraintLeft_toRightOf="@+id/left_guideline"
app:layout_constraintRight_toLeftOf="@+id/center_guideline" />
<com.wismna.geoffroy.donext.widgets.NonSwipeableViewPager
android:id="@+id/container"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_toEndOf="@id/list"
android:background="@android:color/background_light"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:layout_constraintLeft_toRightOf="@+id/center_guideline"
app:layout_constraintRight_toLeftOf="@+id/right_guideline" />
</android.support.constraint.ConstraintLayout>
</android.support.design.widget.CoordinatorLayout>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".activities.AboutActivity">
<TextView
android:id="@+id/version_donext"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/version_android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/about_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="@string/about_link"
android:autoLink="web" />
</LinearLayout>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".activities.MainActivity">
<fragment
android:id="@+id/fragment_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.wismna.geoffroy.donext.fragments.MainFragment"
/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/fab_margin"
android:onClick="onNewTaskClick"
android:src="@drawable/ic_add" />
</android.support.design.widget.CoordinatorLayout>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".activities.TaskListActivity">
<fragment
android:name="com.wismna.geoffroy.donext.fragments.TaskListsFragment"
android:id="@+id/fragment_task_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/fragment_tasklists" />
</LinearLayout>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".activities.TodayActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<include layout="@layout/toolbar" android:id="@+id/toolbar" />
</android.support.design.widget.AppBarLayout>
<fragment
android:name="com.wismna.geoffroy.donext.fragments.TasksFragment"
android:id="@+id/fragment_task_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:layout="@layout/fragment_tasks" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/fab_margin"
android:onClick="onNewTaskClick"
android:src="@drawable/ic_add" />
</android.support.design.widget.CoordinatorLayout>

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/background_light">
<RelativeLayout
android:id="@+id/new_task_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/text_margin"
android:orientation="vertical"
android:focusable="true"
android:focusableInTouchMode="true"
tools:context=".activities.MainActivity">
<TextView
android:id="@+id/new_task_list_label"
android:text="@string/new_task_list"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_marginTop="3dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Spinner
android:id="@+id/new_task_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_toEndOf="@id/new_task_list_label">
</Spinner>
<EditText
android:id="@+id/new_task_name"
android:hint="@string/new_task_name_hint"
android:maxLines="1"
android:inputType="text"
android:textSize="30sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/new_task_list"
android:imeOptions="flagNoFullscreen"/>
<EditText
android:id="@+id/new_task_description"
android:hint="@string/new_task_description_hint"
android:gravity="top|start"
android:lines="3"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/new_task_name"
android:imeOptions="flagNoFullscreen" />
<TextView
android:id="@+id/new_task_priority_label"
android:text="@string/new_task_priority"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_below="@id/new_task_description" />
<SeekBar
android:id="@+id/new_task_priority"
android:max="2"
android:progress="1"
android:layout_width="300dp"
android:layout_height="30dp"
android:layout_toEndOf="@id/new_task_priority_label"
android:layout_below="@id/new_task_description" />
<TextView
android:id="@+id/new_task_priority_tooltip"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:padding="10dp"
android:layout_above="@id/new_task_priority"
android:layout_centerHorizontal="true"
android:background="@android:color/darker_gray"
android:textColor="@android:color/white"
android:textAlignment="center"
android:visibility="gone" />
<CheckBox
android:id="@+id/new_task_today"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
android:layout_below="@id/new_task_priority"
android:layout_alignParentEnd="true" />
<TextView
android:id="@+id/new_task_today_label"
android:text="@string/new_task_today"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:visibility="visible"
android:layout_below="@id/new_task_priority" />
<CheckBox
android:id="@+id/new_task_due_date_set"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/new_task_today"
android:layout_alignParentEnd="true" />
<TextView
android:id="@+id/new_task_due_date_label"
android:text="@string/new_task_due_date"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_below="@id/new_task_today" />
<DatePicker
android:id="@+id/new_task_due_date"
android:datePickerMode="spinner"
android:calendarViewShown="false"
android:spinnersShown="true"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/new_task_due_date_label" />
</RelativeLayout>
</ScrollView>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:focusableInTouchMode="true"
android:background="@android:color/background_light" >
<EditText
android:id="@+id/today_search"
android:hint="@string/today_search_hint"
android:maxLines="1"
android:inputType="text"
android:textSize="30sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="flagNoFullscreen" />
<ListView
android:id="@+id/today_tasks"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textFilterEnabled="true"
android:drawSelectorOnTop="true"
android:choiceMode="multipleChoice">
</ListView>
</LinearLayout>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<include layout="@layout/toolbar" android:id="@+id/dialog_toolbar" />
</android.support.design.widget.AppBarLayout>
<!-- This will contain the actual contents of the dialog -->
<FrameLayout
android:id="@+id/dynamic_fragment_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/incompatible_sdk_version"/>
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>

View File

@@ -0,0 +1,51 @@
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.wismna.geoffroy.donext.fragments.MainFragment">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/appbar_padding_top"
android:theme="@style/AppTheme.AppBarOverlay">
<include layout="@layout/toolbar" android:id="@+id/toolbar" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/left_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:contentDescription="@string/tab_left_arrow"
android:src="@drawable/ic_keyboard_arrow_left_white_24dp" />
<ImageView
android:id="@+id/right_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:contentDescription="@string/tab_right_arrow"
android:src="@drawable/ic_keyboard_arrow_right_white_24dp" />
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@+id/left_arrow"
android:layout_toStartOf="@+id/right_arrow"
app:tabMode="scrollable" />
</RelativeLayout>
</android.support.design.widget.AppBarLayout>
<com.wismna.geoffroy.donext.widgets.NonSwipeableViewPager
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<CheckBox
android:id="@+id/task_confirmation_never"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/text_margin"
android:layout_marginTop="10dp"
android:text="@string/task_confirmation_never_button" />
</LinearLayout>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="70dp"
android:paddingTop="5dp"
android:orientation="horizontal"
android:focusable="true"
android:background="?android:attr/selectableItemBackground" >
<TextView
android:id="@+id/task_cycle"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:textAppearance="?attr/textAppearanceListItem" />
<TextView
android:id="@+id/task_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
<ImageView
android:id="@+id/task_alarm"
android:layout_width="24dp"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:layout_marginEnd="5dp"
android:contentDescription="@string/task_alarm"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="?listPreferredItemHeight"
android:orientation="vertical">
<TextView
android:id="@+id/task_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?attr/textAppearanceListItem" />
<TextView
android:id="@+id/task_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="2"
android:textColor="@color/colorPrimary"
android:textSize="14sp"
android:textAppearance="?attr/textAppearanceListItemSmall" />
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="70dp"
android:orientation="horizontal"
android:background="?android:attr/selectableItemBackground" >
<TextView
android:id="@+id/task_cycle"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:paddingTop="10dp"
android:textAppearance="?attr/textAppearanceListItem" />
<TextView
android:id="@+id/task_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
<ImageView
android:id="@+id/task_alarm"
android:layout_width="24dp"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:layout_marginEnd="5dp"
android:layout_marginTop="10dp"
android:contentDescription="@string/task_alarm"/>
<TextView
android:id="@+id/task_name"
android:layout_marginTop="15dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?attr/textAppearanceListItem"
android:textSize="25sp"/>
</LinearLayout>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/handle"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|start"
android:scaleType="center"
android:src="@drawable/ic_reorder"
android:contentDescription="@string/task_list_drag_handle"/>
<TextView
android:id="@+id/task_list_count"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<EditText
android:id="@+id/task_list_name"
android:layout_width="0dp"
android:layout_height="?listPreferredItemHeight"
android:layout_weight="2"
android:inputType="text"
android:hint="@string/task_list_edit_list_hint"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<Button
android:id="@+id/task_list_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="@string/task_list_delete" />
</LinearLayout>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/new_task_list_parent_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusableInTouchMode="true"
android:descendantFocusability="beforeDescendants"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".activities.TaskListActivity">
<LinearLayout
android:id="@+id/new_task_list_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="75dp">
<EditText
android:id="@+id/new_task_list_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:hint="@string/task_list_new_list_hint"
android:maxLines="1"
android:inputType="text" />
<Button
android:id="@+id/new_task_list_button"
android:layout_width="80dp"
android:layout_height="wrap_content"
style="@style/Widget.AppCompat.Button.Colored"
android:text="@string/task_list_new_list_create"/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/task_lists_view"
android:name="com.wismna.geoffroy.donext.fragments.TaskListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="LinearLayoutManager"
tools:context=".fragments.TaskListsFragment"
tools:listitem="@layout/fragment_tasklist" />
</LinearLayout>

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/task_select" >
<TextView
android:id="@+id/total_task_cycles"
android:layout_width="100dp"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/total_task_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|center"/>
<TextView
android:id="@+id/no_more_tasks"
android:text="@string/task_no_tasks"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|center"
android:visibility="gone"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/task_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="15dp"
android:name="com.wismna.geoffroy.donext.activities.TaskFragment"
app:layoutManager="LinearLayoutManager"
tools:context=".fragments.TasksFragment"
tools:listitem="@layout/fragment_task_detailed" />
<RelativeLayout
android:id="@+id/task_list_background"
android:layout_marginLeft="@dimen/text_margin"
android:layout_marginRight="@dimen/text_margin"
android:layout_height="70dp"
android:layout_width="match_parent"
android:background="@color/colorAccent"
android:visibility="gone">
<TextView
android:id="@+id/task_background_done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:text="@string/task_confirmation_done_button"
android:textAllCaps="true"
android:textSize="20sp"
android:textColor="@android:color/white"
android:visibility="gone"/>
<TextView
android:id="@+id/task_background_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:text="@string/task_confirmation_next_button"
android:textAllCaps="true"
android:textSize="20sp"
android:textColor="@android:color/white"
android:visibility="gone"/>
</RelativeLayout>
<TextView
android:id="@+id/remaining_task_count"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"/>
</FrameLayout>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/task_list_item_layout"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/task_list_item_tasklist"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/colorPrimaryDark"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="4dp" />
<TextView
android:id="@+id/task_list_item_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:layout_marginStart="20dp"
android:layout_marginBottom="4dp"/>
</LinearLayout>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="15dp"
android:textSize="15sp" />

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="enterAlways"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_positive_button"
android:orderInCategory="100"
android:title="@android:string/ok"
app:showAsAction="always"/>
<item
android:id="@+id/menu_neutral_button"
android:orderInCategory="50"
android:title="@android:string/untitled"
app:showAsAction="ifRoom"/>
</menu>

View File

@@ -0,0 +1,52 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".activities.MainActivity">
<!--<item
android:id="@+id/action_newTask"
android:orderInCategory="10"
android:title="@string/action_new_task"
android:onClick="openNewTaskDialog"
app:showAsAction="never" />-->
<item
android:id="@+id/action_todayList"
android:orderInCategory="15"
android:title="@string/action_todayList"
android:onClick="showTodayList"
android:icon="@drawable/ic_stat_name"
android:visible="false"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_changeLayout"
android:orderInCategory="20"
android:title="@string/action_changeLayout"
android:onClick="changeLayout"
android:icon="@drawable/ic_format_size_dark"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_editTabs"
android:orderInCategory="25"
android:title="@string/action_editTabs"
android:onClick="openTaskLists"
android:icon="@drawable/ic_list_white_24dp"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_history"
android:orderInCategory="25"
android:title="@string/action_history"
android:onClick="openHistory"
android:icon="@drawable/ic_list_white_24dp"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_settings"
android:orderInCategory="30"
android:title="@string/action_settings"
android:onClick="openSettings"
app:showAsAction="never" />
<item
android:id="@+id/action_about"
android:orderInCategory="40"
android:title="@string/action_about"
android:onClick="openAbout"
app:showAsAction="never" />
</menu>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_changeLayout"
android:orderInCategory="20"
android:title="@string/action_changeLayout"
android:onClick="changeLayout"
android:icon="@drawable/ic_format_size_dark"
app:showAsAction="always" />
</menu>

Some files were not shown because too many files have changed in this diff Show More