diff --git a/Ganttproject_mobile/.idea/assetWizardSettings.xml b/Ganttproject_mobile/.idea/assetWizardSettings.xml
new file mode 100644
index 0000000..8da1b54
--- /dev/null
+++ b/Ganttproject_mobile/.idea/assetWizardSettings.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Ganttproject_mobile/.idea/caches/build_file_checksums.ser b/Ganttproject_mobile/.idea/caches/build_file_checksums.ser
index 0c9b48a..5f68904 100644
Binary files a/Ganttproject_mobile/.idea/caches/build_file_checksums.ser and b/Ganttproject_mobile/.idea/caches/build_file_checksums.ser differ
diff --git a/Ganttproject_mobile/.idea/misc.xml b/Ganttproject_mobile/.idea/misc.xml
index 3b488f3..19984ab 100644
--- a/Ganttproject_mobile/.idea/misc.xml
+++ b/Ganttproject_mobile/.idea/misc.xml
@@ -25,7 +25,7 @@
-
+
diff --git a/Ganttproject_mobile/.idea/vcs.xml b/Ganttproject_mobile/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/Ganttproject_mobile/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Ganttproject_mobile/app/build.gradle b/Ganttproject_mobile/app/build.gradle
index 2fa9529..2ed9f94 100644
--- a/Ganttproject_mobile/app/build.gradle
+++ b/Ganttproject_mobile/app/build.gradle
@@ -3,9 +3,10 @@ apply plugin: 'com.google.protobuf'
android {
compileSdkVersion 27
+ buildToolsVersion "27.0.3"
defaultConfig {
applicationId "com.bardsoftware.ganttproject_mobile"
- minSdkVersion 15
+ minSdkVersion 23
targetSdkVersion 27
versionCode 1
versionName "1.0"
@@ -19,6 +20,9 @@ android {
}
}
+/*sourceSets {
+ main.java.srcDirs += "${protobuf.generatedFilesBaseDir}/main/javalite"
+}*/
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.0.0'
@@ -34,7 +38,7 @@ protobuf {
remove java
}
task.plugins {
- javalite { }
+ javalite {}
}
}
}
@@ -44,9 +48,21 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
- testImplementation 'junit:junit:4.12'
+ implementation 'com.android.support:design:27.1.1'
+
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+ implementation 'com.android.support:recyclerview-v7:27.1.1'
+
+ implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'com.google.protobuf:protobuf-lite:3.0.0'
+
+ implementation 'com.jakewharton:butterknife:8.8.1'
+ annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
+
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', {
+ exclude group: 'com.android.support', module: 'support-annotations'
+ })
}
diff --git a/Ganttproject_mobile/app/src/main/AndroidManifest.xml b/Ganttproject_mobile/app/src/main/AndroidManifest.xml
index bbcc2fd..a8ef1b7 100644
--- a/Ganttproject_mobile/app/src/main/AndroidManifest.xml
+++ b/Ganttproject_mobile/app/src/main/AndroidManifest.xml
@@ -2,6 +2,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Ganttproject_mobile/app/src/main/java/com/bardsoftware/ganttproject_mobile/Constants.java b/Ganttproject_mobile/app/src/main/java/com/bardsoftware/ganttproject_mobile/Constants.java
new file mode 100644
index 0000000..aec4a0b
--- /dev/null
+++ b/Ganttproject_mobile/app/src/main/java/com/bardsoftware/ganttproject_mobile/Constants.java
@@ -0,0 +1,5 @@
+package com.bardsoftware.ganttproject_mobile;
+
+public class Constants {
+ public static final String FILE_PATH = "FilePath";
+}
diff --git a/Ganttproject_mobile/app/src/main/java/com/bardsoftware/ganttproject_mobile/MainActivity.java b/Ganttproject_mobile/app/src/main/java/com/bardsoftware/ganttproject_mobile/MainActivity.java
index c48c5a0..7c48533 100644
--- a/Ganttproject_mobile/app/src/main/java/com/bardsoftware/ganttproject_mobile/MainActivity.java
+++ b/Ganttproject_mobile/app/src/main/java/com/bardsoftware/ganttproject_mobile/MainActivity.java
@@ -7,7 +7,7 @@
public class MainActivity extends AppCompatActivity {
- private static final int OPEN_FILE_CODE = 100 ;
+ private static final int OPEN_FILE_CODE = 100;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -16,14 +16,20 @@ protected void onCreate(Bundle savedInstanceState) {
}
public void openProtoFile(View view) {
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
- intent.setType("*/*");
+ Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.setType("application/octet-stream");
startActivityForResult(intent, OPEN_FILE_CODE);
}
+
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == OPEN_FILE_CODE && resultCode == RESULT_OK && data != null)
- { String filePath = data.getDataString();
- // do somthing...
+ if (requestCode == OPEN_FILE_CODE && resultCode == RESULT_OK && data != null) {
+ String filePath = data.getDataString();
+ Bundle b = new Bundle();
+ b.putString(Constants.FILE_PATH, filePath);
+ Class TasksActivity = TasksActivity.class;
+ Intent intent = new Intent(this, TasksActivity);
+ intent.putExtras(b);
+ startActivity(intent);
}
super.onActivityResult(requestCode, resultCode, data);
diff --git a/Ganttproject_mobile/app/src/main/java/com/bardsoftware/ganttproject_mobile/TaskAdapter.java b/Ganttproject_mobile/app/src/main/java/com/bardsoftware/ganttproject_mobile/TaskAdapter.java
new file mode 100644
index 0000000..837ffda
--- /dev/null
+++ b/Ganttproject_mobile/app/src/main/java/com/bardsoftware/ganttproject_mobile/TaskAdapter.java
@@ -0,0 +1,134 @@
+package com.bardsoftware.ganttproject_mobile;
+
+import android.content.Context;
+import android.graphics.Paint;
+import android.support.annotation.NonNull;
+import android.support.v7.widget.RecyclerView;
+import android.util.SparseBooleanArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.ImageButton;
+import android.widget.TextView;
+import android.view.View.OnClickListener;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+import static dataformat.Dataformat.Task;
+import static dataformat.Dataformat.Tasks;
+
+public class TaskAdapter extends RecyclerView.Adapter {
+ private Tasks.Builder tasksBuilder;
+ private SparseBooleanArray taskStateArray = new SparseBooleanArray();
+ private int currentSelectedPosition = RecyclerView.NO_POSITION;
+
+ @NonNull
+ @Override
+ public TaskViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ Context context = parent.getContext();
+ LayoutInflater inflater = LayoutInflater.from(context);
+ View view = inflater.inflate(R.layout.task_row, parent, false);
+ return new TaskAdapter.TaskViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull TaskViewHolder holder, final int position) {
+ if (tasksBuilder == null) return;
+ String taskName = tasksBuilder.getTask(position).getName();
+ boolean itemIsChecked = tasksBuilder.getTask(position).getIsDone();
+ taskStateArray.append(position, itemIsChecked);
+ holder.taskView.setText(taskName);
+ holder.taskCheckbox.setChecked(itemIsChecked);
+ if (itemIsChecked) {
+ holder.taskView.setPaintFlags(holder.taskView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
+ } else
+ holder.taskView.setPaintFlags(holder.taskView.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
+ if (currentSelectedPosition == position) {
+ holder.deleteButton.setVisibility(View.VISIBLE);
+ holder.deleteButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ tasksBuilder.removeTask(position);
+ taskStateArray.delete(position);
+ notifyDataSetChanged();
+
+ }
+ });
+ } else {
+ holder.deleteButton.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ if (tasksBuilder == null) return 0;
+ return tasksBuilder.getTaskCount();
+ }
+
+ public void setData(Tasks tasks1) {
+ tasksBuilder = tasks1.toBuilder();
+ notifyDataSetChanged();
+ }
+
+ public Tasks getTasks() {
+ Tasks.Builder tasks1 = Tasks.newBuilder();
+ for (int i = 0; i < getItemCount(); i++) {
+ Task task = Task.newBuilder()
+ .setName(tasksBuilder.getTask(i).getName())
+ .setIsDone(tasksBuilder.getTask(i).getIsDone())
+ .build();
+ tasks1.addTask(task);
+ }
+ return tasks1.build();
+ }
+
+ public void addTask(String name) {
+ Task task = Task.newBuilder().setName(name).setIsDone(false).build();
+ tasksBuilder.addTask(task);
+ taskStateArray.append(tasksBuilder.getTaskCount(), false);
+ notifyDataSetChanged();
+ }
+
+ public class TaskViewHolder extends RecyclerView.ViewHolder {
+ @BindView(R.id.task_textview)
+ TextView taskView;
+ @BindView(R.id.task_checkbox)
+ CheckBox taskCheckbox;
+ @BindView(R.id.delete_task_button)
+ ImageButton deleteButton;
+
+ TaskViewHolder(View view) {
+ super(view);
+ ButterKnife.bind(this, view);
+ taskView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ currentSelectedPosition = getAdapterPosition();
+ notifyDataSetChanged();
+ }
+ });
+ taskCheckbox.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ int adapterPosition = getAdapterPosition();
+ if (!taskStateArray.get(adapterPosition, false)) {
+ taskCheckbox.setChecked(true);
+ taskView.setPaintFlags(taskView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
+ taskStateArray.put(adapterPosition, true);
+ Task task1 = Task.newBuilder().setName(tasksBuilder.getTask(adapterPosition).getName()).setIsDone(true).build();
+ tasksBuilder.setTask(adapterPosition, task1);
+ } else {
+ taskCheckbox.setChecked(false);
+ taskStateArray.put(adapterPosition, false);
+ taskView.setPaintFlags(taskView.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
+ Task task1 = Task.newBuilder().setName(tasksBuilder.getTask(adapterPosition).getName()).setIsDone(false).build();
+ tasksBuilder.setTask(adapterPosition, task1);
+ }
+ currentSelectedPosition = getAdapterPosition();
+ notifyDataSetChanged();
+ }
+ });
+ }
+ }
+}
diff --git a/Ganttproject_mobile/app/src/main/java/com/bardsoftware/ganttproject_mobile/TasksActivity.java b/Ganttproject_mobile/app/src/main/java/com/bardsoftware/ganttproject_mobile/TasksActivity.java
new file mode 100644
index 0000000..70d49bc
--- /dev/null
+++ b/Ganttproject_mobile/app/src/main/java/com/bardsoftware/ganttproject_mobile/TasksActivity.java
@@ -0,0 +1,130 @@
+package com.bardsoftware.ganttproject_mobile;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Parcelable;
+import android.support.v4.app.ActivityCompat;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Objects;
+
+import static dataformat.Dataformat.Tasks;
+
+public class TasksActivity extends AppCompatActivity {
+ private Uri filePath;
+ private Context mContext;
+ private TaskAdapter taskAdapter;
+ private Tasks tasks;
+ //@BindView(R.id.tasks_recyclerview)
+ RecyclerView tasksRecyclerView;
+ private static final String LAYOUT_POSITION = "position";
+ private static final int REQUEST_EXTERNAL_STORAGE = 1;
+ private static String[] PERMISSIONS_STORAGE = {
+ Manifest.permission.READ_EXTERNAL_STORAGE,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_tasks);
+ mContext = this;
+ if (savedInstanceState == null) {
+ Bundle bundle = getIntent().getExtras();
+ filePath = Uri.parse(Objects.requireNonNull(bundle).getString(Constants.FILE_PATH));
+ }
+ verifyStoragePermissions(this);
+
+ try {
+ InputStream input = mContext.getContentResolver().openInputStream(filePath);
+ tasks = Tasks.parseFrom(input);
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ tasksRecyclerView = findViewById(R.id.tasks_recyclerview);
+ tasksRecyclerView.setLayoutManager(new LinearLayoutManager(this));
+ taskAdapter = new TaskAdapter();
+ tasksRecyclerView.setAdapter(taskAdapter);
+ taskAdapter.setData(tasks);
+
+ if (savedInstanceState != null) {
+ Parcelable savedRecyclerLayoutState = savedInstanceState.getParcelable("position");
+ tasksRecyclerView.getLayoutManager().onRestoreInstanceState(savedRecyclerLayoutState);
+ }
+ }
+
+ private static void verifyStoragePermissions(Activity activity) {
+ // Check if we have write permission
+ int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
+
+ if (permission != PackageManager.PERMISSION_GRANTED) {
+ // We don't have permission so prompt the user
+ ActivityCompat.requestPermissions(
+ activity,
+ PERMISSIONS_STORAGE,
+ REQUEST_EXTERNAL_STORAGE
+ );
+ }
+ }
+
+ public void saveTasksFile(View view) {
+ taskAdapter.notifyDataSetChanged();
+ tasks = taskAdapter.getTasks();
+ mContext.grantUriPermission("com.bardsoftware.ganttproject_mobile", filePath, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ try {
+
+ OutputStream output = mContext.getContentResolver().openOutputStream(filePath);
+ tasks.writeTo(Objects.requireNonNull(output));
+ output.close();
+ Toast.makeText(this, "file " + filePath.getPath() + " is saved", Toast.LENGTH_LONG).show();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void addTaskClicked(View view) {
+ taskAdapter.notifyDataSetChanged();
+
+ final EditText taskTitleEditText = new EditText(mContext);
+ AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+ builder.setTitle("Add New Task");
+ builder.setView(taskTitleEditText);
+
+ builder.setPositiveButton("Add", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ String taskTitle = String.valueOf(taskTitleEditText.getText());
+ taskAdapter.addTask(taskTitle);
+ }
+
+ });
+ builder.setNegativeButton("Cancel", null);
+ AlertDialog dialog = builder.create();
+ dialog.show();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelable(LAYOUT_POSITION, tasksRecyclerView.getLayoutManager().onSaveInstanceState());
+ }
+}
diff --git a/Ganttproject_mobile/app/src/main/proto/dataformat.proto b/Ganttproject_mobile/app/src/main/proto/dataformat.proto
new file mode 100644
index 0000000..4e2f2bd
--- /dev/null
+++ b/Ganttproject_mobile/app/src/main/proto/dataformat.proto
@@ -0,0 +1,10 @@
+syntax = "proto3";
+package dataformat;
+
+message Task {
+ string name = 1;
+ bool is_done = 2;
+}
+message Tasks {
+ repeated Task task= 1;
+}
\ No newline at end of file
diff --git a/Ganttproject_mobile/app/src/main/res/drawable/ic_add_24dp.xml b/Ganttproject_mobile/app/src/main/res/drawable/ic_add_24dp.xml
new file mode 100644
index 0000000..e500af0
--- /dev/null
+++ b/Ganttproject_mobile/app/src/main/res/drawable/ic_add_24dp.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Ganttproject_mobile/app/src/main/res/drawable/ic_delete_black_24dp.xml b/Ganttproject_mobile/app/src/main/res/drawable/ic_delete_black_24dp.xml
new file mode 100644
index 0000000..4ebb6e8
--- /dev/null
+++ b/Ganttproject_mobile/app/src/main/res/drawable/ic_delete_black_24dp.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Ganttproject_mobile/app/src/main/res/layout/activity_tasks.xml b/Ganttproject_mobile/app/src/main/res/layout/activity_tasks.xml
new file mode 100644
index 0000000..e779111
--- /dev/null
+++ b/Ganttproject_mobile/app/src/main/res/layout/activity_tasks.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Ganttproject_mobile/app/src/main/res/layout/task_row.xml b/Ganttproject_mobile/app/src/main/res/layout/task_row.xml
new file mode 100644
index 0000000..f39e451
--- /dev/null
+++ b/Ganttproject_mobile/app/src/main/res/layout/task_row.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Ganttproject_mobile/app/src/main/res/values/dimens.xml b/Ganttproject_mobile/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..0b07d22
--- /dev/null
+++ b/Ganttproject_mobile/app/src/main/res/values/dimens.xml
@@ -0,0 +1,8 @@
+
+
+ 10dp
+ 14sp
+ 5dp
+ 3dp
+ 57dp
+
\ No newline at end of file
diff --git a/Ganttproject_mobile/app/src/main/res/values/strings.xml b/Ganttproject_mobile/app/src/main/res/values/strings.xml
index 068f65f..4b3ed53 100644
--- a/Ganttproject_mobile/app/src/main/res/values/strings.xml
+++ b/Ganttproject_mobile/app/src/main/res/values/strings.xml
@@ -1,4 +1,6 @@
- Ganttproject_mobile
+ Ganttproject mobile
Open
+ Save
+ trash can
diff --git a/Ganttproject_mobile/build.gradle b/Ganttproject_mobile/build.gradle
index 9a2f6a1..fe6e92c 100644
--- a/Ganttproject_mobile/build.gradle
+++ b/Ganttproject_mobile/build.gradle
@@ -1,6 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
+
repositories {
google()