diff --git a/app/build.gradle b/app/build.gradle index 5c04260..d25d34e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,7 +5,7 @@ android { buildToolsVersion "23.0.2" defaultConfig { - applicationId "com.csc.lesson6" + applicationId "ru.ppzh.todolist" minSdkVersion 15 targetSdkVersion 23 versionCode 1 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7ab0b4b..bac12ae 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ + package="ru.ppzh.todolist"> @@ -18,11 +18,13 @@ + + + android:exported="false"/> \ No newline at end of file diff --git a/app/src/main/java/com/csc/lesson6/FeedsTable.java b/app/src/main/java/com/csc/lesson6/FeedsTable.java deleted file mode 100644 index be48cec..0000000 --- a/app/src/main/java/com/csc/lesson6/FeedsTable.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.csc.lesson6; - -import android.provider.BaseColumns; - -interface FeedsTable extends BaseColumns { - String TABLE_NAME = "feeds"; - - String COLUMN_TITLE = "title"; - String COLUMN_DATE = "date"; - String COLUMN_CONTENT = "content"; -} diff --git a/app/src/main/java/com/csc/lesson6/MainActivity.java b/app/src/main/java/com/csc/lesson6/MainActivity.java deleted file mode 100644 index 14ccad0..0000000 --- a/app/src/main/java/com/csc/lesson6/MainActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.csc.lesson6; - -import android.content.ContentValues; -import android.database.ContentObserver; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.support.v7.app.AppCompatActivity; -import android.util.Log; -import android.view.View; - -import static com.csc.lesson6.FeedsTable.COLUMN_CONTENT; -import static com.csc.lesson6.FeedsTable.COLUMN_TITLE; - -public class MainActivity extends AppCompatActivity { - public static final String TAG = "MainActivity"; - - public static final Uri ENTRIES_URI = Uri.withAppendedPath(ReaderContentProvider.CONTENT_URI, "entries"); - - private final ContentObserver observer = new ContentObserver(new Handler()) { - @Override - public void onChange(boolean selfChange) { - super.onChange(selfChange); - Log.d(TAG, "ContentObserver: onChange"); - } - }; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.main); - - Cursor cursor = managedQuery(ENTRIES_URI, - null, null, null, null); - - cursor.registerContentObserver(observer); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - getContentResolver().unregisterContentObserver(observer); - } - - public void addData(View view) { - ContentValues values = new ContentValues(); - values.put(COLUMN_TITLE, - "new title3"); - values.put(FeedsTable.COLUMN_CONTENT, - ""); - values.put(FeedsTable.COLUMN_DATE, - "Mon, 28 Mar 2016 19:04:05 +0300"); - getContentResolver().insert( - ENTRIES_URI, - values); - } -} diff --git a/app/src/main/java/com/csc/lesson6/ReaderOpenHelper.java b/app/src/main/java/com/csc/lesson6/ReaderOpenHelper.java deleted file mode 100644 index 368bb0a..0000000 --- a/app/src/main/java/com/csc/lesson6/ReaderOpenHelper.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.csc.lesson6; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; - -public class ReaderOpenHelper extends SQLiteOpenHelper { - public static final int DATABASE_VERSION = 2; - public static final String DATABASE_NAME = "reader.db"; - - private static final String SQL_CREATE_ENTRIES_TABLE = - "CREATE TABLE " + FeedsTable.TABLE_NAME - + "(" - + FeedsTable._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " - + FeedsTable.COLUMN_TITLE + " TEXT, " - + FeedsTable.COLUMN_CONTENT + " TEXT, " - + FeedsTable.COLUMN_DATE + " TEXT" - + ")"; - - private static final String SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS " + FeedsTable.TABLE_NAME; - - public ReaderOpenHelper(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - } - - public void onCreate(SQLiteDatabase db) { - db.execSQL(SQL_CREATE_ENTRIES_TABLE); - } - - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - db.execSQL(SQL_DELETE_ENTRIES); - switch (oldVersion) { - case 1: -// ... - break; - case 2: -// ... - break; - default: - throw new IllegalStateException(); - } - onCreate(db); - } -} diff --git a/app/src/main/java/ru/ppzh/todolist/MainActivity.java b/app/src/main/java/ru/ppzh/todolist/MainActivity.java new file mode 100644 index 0000000..73eece0 --- /dev/null +++ b/app/src/main/java/ru/ppzh/todolist/MainActivity.java @@ -0,0 +1,94 @@ +package ru.ppzh.todolist; + +import android.content.ContentValues; +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.AdapterView; +import android.widget.EditText; +import android.widget.ListView; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class MainActivity extends AppCompatActivity + implements LoaderManager.LoaderCallbacks { + public static final String TASK_ID_EXTRA = + "ru.ppzh.dotolist.task_id"; + public static final String DATE_FORMAT = "EEE, d MMM yyyy HH:mm"; + public static final String SORT_ORDER = TasksTable.COLUMN_COMPLETED + ", " + + TasksTable.COLUMN_FAVORITE + " DESC, " + + TasksTable.COLUMN_DATE + " DESC"; + + public static final Uri TASKS_URI = Uri.withAppendedPath(ToDoListContentProvider.CONTENT_URI, "tasks"); + + TaskCursorAdapter adapter; + + ListView list; + EditText taskInput; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + adapter = new TaskCursorAdapter(this, null); + + list = (ListView) findViewById(R.id.listView); + list.setAdapter(adapter); + + taskInput = (EditText) findViewById(R.id.task_text_input); + + list.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + Intent i = new Intent(getApplicationContext(), TaskEditActivity.class); + i.putExtra(TASK_ID_EXTRA, id); + startActivity(i); + } + }); + + getSupportLoaderManager().initLoader(0, null, this); + } + + public void addData(View view) { + ContentValues values = new ContentValues(); + SimpleDateFormat format = + new SimpleDateFormat(DATE_FORMAT, Locale.getDefault()); + values.put( + TasksTable.COLUMN_TEXT, + taskInput.getText().toString() + ); + values.put(TasksTable.COLUMN_DATE, + format.format(new Date())); + values.put(TasksTable.COLUMN_COMPLETED, + "False"); + values.put(TasksTable.COLUMN_FAVORITE, + "False"); + getContentResolver().insert( + TASKS_URI, + values); + } + + @Override + public Loader onCreateLoader(int id, Bundle args) { + return new CursorLoader(this, TASKS_URI, null, null, null, SORT_ORDER); + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + adapter.swapCursor(new TaskCursor(data)); + } + + @Override + public void onLoaderReset(Loader loader) { + adapter.swapCursor(null); + } +} diff --git a/app/src/main/java/ru/ppzh/todolist/Task.java b/app/src/main/java/ru/ppzh/todolist/Task.java new file mode 100644 index 0000000..8a73777 --- /dev/null +++ b/app/src/main/java/ru/ppzh/todolist/Task.java @@ -0,0 +1,87 @@ +package ru.ppzh.todolist; + + +import android.support.annotation.NonNull; + +import java.util.Date; + + +public class Task implements Comparable { + private long id; + private boolean completed; + private boolean favorite; + private String text; + private String date; + + Task() { + id = -1; + completed = false; + favorite = false; + this.text = ""; + date = new Date().toString(); + } + + Task(String text) { + this(); + this.text = text; + } + + @Override + public int compareTo(@NonNull Task o) { + if (!completed == o.completed) { + return 1; + } + if (completed == !o.completed) { + return -1; + } + if (completed == o.completed) { + if (favorite == !o.favorite) { + return 1; + } + if (!favorite == o.favorite) { + return -1; + } + } + return date.compareTo(o.date); + } + + public boolean isCompleted() { + return completed; + } + + public void setCompleted(boolean completed) { + this.completed = completed; + } + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public boolean isFavorite() { + return favorite; + } + + public void setFavorite(boolean favorite) { + this.favorite = favorite; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } +} diff --git a/app/src/main/java/ru/ppzh/todolist/TaskCursor.java b/app/src/main/java/ru/ppzh/todolist/TaskCursor.java new file mode 100644 index 0000000..d41a5ae --- /dev/null +++ b/app/src/main/java/ru/ppzh/todolist/TaskCursor.java @@ -0,0 +1,27 @@ +package ru.ppzh.todolist; + +import android.database.Cursor; +import android.database.CursorWrapper; + +public class TaskCursor extends CursorWrapper { + public TaskCursor(Cursor cursor) { + super(cursor); + } + + public Task getTask() { + if (isBeforeFirst() || isAfterLast()) { + return null; + } + Task task = new Task(); + task.setId(getLong(getColumnIndex(TasksTable._ID))); + task.setText(getString(getColumnIndex(TasksTable.COLUMN_TEXT))); + task.setDate(getString(getColumnIndex(TasksTable.COLUMN_DATE))); + task.setCompleted(Boolean.parseBoolean( + getString(getColumnIndex(TasksTable.COLUMN_COMPLETED)) + )); + task.setFavorite(Boolean.parseBoolean( + getString(getColumnIndex(TasksTable.COLUMN_FAVORITE)) + )); + return task; + } +} diff --git a/app/src/main/java/ru/ppzh/todolist/TaskCursorAdapter.java b/app/src/main/java/ru/ppzh/todolist/TaskCursorAdapter.java new file mode 100644 index 0000000..1ee4c14 --- /dev/null +++ b/app/src/main/java/ru/ppzh/todolist/TaskCursorAdapter.java @@ -0,0 +1,61 @@ +package ru.ppzh.todolist; + +import android.content.Context; +import android.database.Cursor; +import android.graphics.Paint; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CursorAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +public class TaskCursorAdapter extends CursorAdapter { + public static final String TAG = "TaskCursorAdapter"; + + private Context context; + private TaskCursor taskCursor; + + public TaskCursorAdapter(Context context, TaskCursor c) { + super(context, c, 0); + this.taskCursor = c; + this.context = context; + } + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + LayoutInflater inflater = + (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + return inflater.inflate(R.layout.item, parent, false); + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + Task task = taskCursor.getTask(); + + TextView date = (TextView) view.findViewById(R.id.date); + TextView text = (TextView) view.findViewById(R.id.task_text); + ImageView fav = (ImageView) view.findViewById(R.id.favorite_img); + + date.setText(task.getDate()); + text.setText(task.getText()); + fav.setVisibility( + task.isFavorite() ? View.VISIBLE : View.INVISIBLE + ); + if (task.isCompleted()) { + + Log.d(TAG, "task is completed - " + task.getId()); + + text.setPaintFlags(text.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); + } else { + text.setPaintFlags(text.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG); + } + } + + @Override + public Cursor swapCursor(Cursor newCursor) { + taskCursor = (TaskCursor) newCursor; + return super.swapCursor(newCursor); + } +} diff --git a/app/src/main/java/ru/ppzh/todolist/TaskEditActivity.java b/app/src/main/java/ru/ppzh/todolist/TaskEditActivity.java new file mode 100644 index 0000000..bfcb30f --- /dev/null +++ b/app/src/main/java/ru/ppzh/todolist/TaskEditActivity.java @@ -0,0 +1,98 @@ +package ru.ppzh.todolist; + +import android.content.ContentUris; +import android.content.ContentValues; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class TaskEditActivity extends AppCompatActivity + implements LoaderManager.LoaderCallbacks { + + private long taskId; + private Task task; + + private EditText taskET; + private CheckBox favoriteCB; + private CheckBox completedCB; + private Button saveBTN; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.task_edit); + taskId = getIntent().getLongExtra(MainActivity.TASK_ID_EXTRA, -1); + + taskET = (EditText) findViewById(R.id.task_text_et); + favoriteCB = (CheckBox) findViewById(R.id.favorite_cb); + completedCB = (CheckBox) findViewById(R.id.completed_cb); + saveBTN = (Button) findViewById(R.id.save_btn); + + saveBTN.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + updateTask(); + finish(); + } + }); + + getSupportLoaderManager().initLoader(1, null, this); + } + + private void updateTask() { + Uri uri = ContentUris.withAppendedId(MainActivity.TASKS_URI, taskId); + ContentValues values = new ContentValues(); + SimpleDateFormat format = + new SimpleDateFormat(MainActivity.DATE_FORMAT, Locale.getDefault()); + + values.put(TasksTable.COLUMN_TEXT, + taskET.getText().toString()); + values.put(TasksTable.COLUMN_DATE, + format.format(new Date())); + values.put(TasksTable.COLUMN_COMPLETED, + Boolean.toString(completedCB.isChecked())); + values.put(TasksTable.COLUMN_FAVORITE, + Boolean.toString(favoriteCB.isChecked())); + + getContentResolver().update(uri, values, null, null); + } + + @Override + public Loader onCreateLoader(int id, Bundle args) { + return new CursorLoader( + this, + MainActivity.TASKS_URI, + null, + "_ID = " + Long.toString(taskId), + null, null + ); + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + TaskCursor taskCursor = new TaskCursor(data); + taskCursor.moveToFirst(); + task = taskCursor.getTask(); + + taskET.setText(task.getText()); + favoriteCB.setChecked(task.isFavorite()); + completedCB.setChecked(task.isCompleted()); + } + + @Override + public void onLoaderReset(Loader loader) { + + } +} diff --git a/app/src/main/java/ru/ppzh/todolist/TasksTable.java b/app/src/main/java/ru/ppzh/todolist/TasksTable.java new file mode 100644 index 0000000..add9b22 --- /dev/null +++ b/app/src/main/java/ru/ppzh/todolist/TasksTable.java @@ -0,0 +1,12 @@ +package ru.ppzh.todolist; + +import android.provider.BaseColumns; + +interface TasksTable extends BaseColumns { + String TABLE_NAME = "tasks"; + + String COLUMN_TEXT = "text"; + String COLUMN_DATE = "date"; + String COLUMN_FAVORITE = "favorite"; + String COLUMN_COMPLETED = "completed"; +} diff --git a/app/src/main/java/com/csc/lesson6/ReaderContentProvider.java b/app/src/main/java/ru/ppzh/todolist/ToDoListContentProvider.java similarity index 59% rename from app/src/main/java/com/csc/lesson6/ReaderContentProvider.java rename to app/src/main/java/ru/ppzh/todolist/ToDoListContentProvider.java index f8e6c21..05ab48f 100644 --- a/app/src/main/java/com/csc/lesson6/ReaderContentProvider.java +++ b/app/src/main/java/ru/ppzh/todolist/ToDoListContentProvider.java @@ -1,4 +1,4 @@ -package com.csc.lesson6; +package ru.ppzh.todolist; import android.content.ContentProvider; import android.content.ContentUris; @@ -9,49 +9,49 @@ import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.support.annotation.NonNull; +import android.util.Log; -public class ReaderContentProvider extends ContentProvider { - public static final String AUTHORITY = "com.csc.lesson6"; +public class ToDoListContentProvider extends ContentProvider { + public static final String TAG = "ToDoListContentProvider"; + + public static final String AUTHORITY = "ru.ppzh.todolist.provider"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); - public static final int ENTRIES = 1; - public static final int ENTRIES_ID = 2; + public static final int TASKS = 1; + public static final int TASKS_ID = 2; private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { - uriMatcher.addURI(AUTHORITY, "/entries", ENTRIES); - uriMatcher.addURI(AUTHORITY, "/entries/#", ENTRIES_ID); + uriMatcher.addURI(AUTHORITY, "/tasks", TASKS); + uriMatcher.addURI(AUTHORITY, "/tasks/#", TASKS_ID); } - private ReaderOpenHelper helper; + private ToDoListDatabaseHelper helper; - public ReaderContentProvider() { - helper = new ReaderOpenHelper(getContext()); + public ToDoListContentProvider() { + helper = new ToDoListDatabaseHelper(getContext()); } - @Override - public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) { - // Implement this to handle requests to delete one or more rows. - throw new UnsupportedOperationException("Not yet implemented"); - } @Override - public String getType(@NonNull Uri uri) { - // TODO: Implement this to handle requests for the MIME type of the data - // at the given URI. - throw new UnsupportedOperationException("Not yet implemented"); + public boolean onCreate() { + helper = new ToDoListDatabaseHelper(getContext()); + return true; } @Override public Uri insert(@NonNull Uri uri, ContentValues values) { + + Log.d(TAG, "Insertion: " + values.toString()); + int match = uriMatcher.match(uri); String tableName; switch (match) { - case ENTRIES: - tableName = FeedsTable.TABLE_NAME; + case TASKS: + tableName = TasksTable.TABLE_NAME; break; - case ENTRIES_ID: + case TASKS_ID: default: throw new UnsupportedOperationException("Not yet implemented"); } @@ -61,20 +61,17 @@ public Uri insert(@NonNull Uri uri, ContentValues values) { return inserted; } - @Override - public boolean onCreate() { - helper = new ReaderOpenHelper(getContext()); - return true; - } - @Override public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + + Log.d(TAG, "Query"); + int match = uriMatcher.match(uri); SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); switch (match) { - case ENTRIES: - builder.setTables(FeedsTable.TABLE_NAME); + case TASKS: + builder.setTables(TasksTable.TABLE_NAME); break; default: throw new UnsupportedOperationException("Not yet implemented"); @@ -85,10 +82,36 @@ public Cursor query(@NonNull Uri uri, String[] projection, String selection, return cursor; } + @Override + public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) { + throw new UnsupportedOperationException("Not yet implemented"); + } + @Override public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) { - // TODO: Implement this to handle requests to update one or more rows. + + Log.d(TAG, "Updating: " + values.toString()); + + int match = uriMatcher.match(uri); + switch (match) { + case TASKS_ID: + if (selection == null) { + selection = ""; + } + selection = selection + "_ID = " + uri.getLastPathSegment(); + break; + default: + throw new UnsupportedOperationException("Not yet implemented"); + } + int affected = + helper.getWritableDatabase().update(TasksTable.TABLE_NAME, values, selection, selectionArgs); + getContext().getContentResolver().notifyChange(uri, null); + return affected; + } + + @Override + public String getType(@NonNull Uri uri) { throw new UnsupportedOperationException("Not yet implemented"); } } diff --git a/app/src/main/java/ru/ppzh/todolist/ToDoListDatabaseHelper.java b/app/src/main/java/ru/ppzh/todolist/ToDoListDatabaseHelper.java new file mode 100644 index 0000000..1fb28be --- /dev/null +++ b/app/src/main/java/ru/ppzh/todolist/ToDoListDatabaseHelper.java @@ -0,0 +1,38 @@ +package ru.ppzh.todolist; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +public class ToDoListDatabaseHelper extends SQLiteOpenHelper { + public static final String TAG = "ToDoListDatabaseHelper"; + public static final int DATABASE_VERSION = 1; + public static final String DATABASE_NAME = "todolist.db"; + + private static final String SQL_CREATE_TASK_TABLE = + "CREATE TABLE " + TasksTable.TABLE_NAME + + " (" + + TasksTable._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + TasksTable.COLUMN_TEXT + " TEXT, " + + TasksTable.COLUMN_FAVORITE + " BOOLEAN, " + + TasksTable.COLUMN_COMPLETED + " BOOLEAN, " + + TasksTable.COLUMN_DATE + " DATETIME" + + ")"; + + public ToDoListDatabaseHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + public void onCreate(SQLiteDatabase db) { + db.execSQL(SQL_CREATE_TASK_TABLE); + + Log.d(TAG, "Database created."); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + + } + +} diff --git a/app/src/main/res/layout/item.xml b/app/src/main/res/layout/item.xml new file mode 100644 index 0000000..2f72504 --- /dev/null +++ b/app/src/main/res/layout/item.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/main.xml b/app/src/main/res/layout/main.xml index 2970a1c..329da72 100644 --- a/app/src/main/res/layout/main.xml +++ b/app/src/main/res/layout/main.xml @@ -2,13 +2,36 @@ - -