ready to tear my hair out

This commit is contained in:
Wyatt J. Miller 2020-11-14 21:27:49 -05:00
parent 75f681b03b
commit 27b2f5f028
29 changed files with 881 additions and 120 deletions

View File

@ -0,0 +1,7 @@
<component name="ProjectDictionaryState">
<dictionary name="wyatt">
<words>
<w>descripition</w>
</words>
</dictionary>
</component>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View File

@ -1,6 +1,7 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 29
@ -25,15 +26,17 @@ android {
}
dependencies {
def room_version = "2.2.5"
implementation "androidx.room:room-runtime:$room_version"
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.3'
// user implementations
// where are they all at??
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.google.android.material:material:1.2.1'
kapt "androidx.room:room-compiler:$room_version"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

View File

@ -9,13 +9,14 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<activity android:name=".CourseActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SettingsActivity"></activity>
</application>
</manifest>

View File

@ -1,11 +1,20 @@
package com.wyattjmiller.classscheduleapp
class Course {
var id: Long = 0
var id: Int = 0
var name: String? = null
var description: String? = null
var location: String? = null
var dayOfWeek: String? = null
var dayofweek: String? = null
var time: String? = null
var instructor: String? = null
constructor() {}
constructor(courseId: Int) {
this.id = courseId
}
constructor(courseName: String) {
this.name = courseName
}
}

View File

@ -0,0 +1,222 @@
package com.wyattjmiller.classscheduleapp
import android.content.Intent
import android.content.SharedPreferences
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.preference.PreferenceManager
import android.view.*
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class CourseActivity : AppCompatActivity(), CourseDialogFragment.onCourseEnteredListener {
private lateinit var mDialog: CourseDialogFragment
private var mCourseListRecyclerView: RecyclerView? = null
private var mCourseAdapter: CourseAdapter? = null
private lateinit var mCourseDb: CourseDatabase
private lateinit var mSelectedCourse: Course
private var mActionMode: ActionMode? = null
private var mSharedPrefs: SharedPreferences? = null
private var mDarkTheme = false
private var mSelectedCoursePosition = RecyclerView.NO_POSITION
// when the app first starts
override fun onCreate(savedInstanceState: Bundle?) {
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this)
mDarkTheme = mSharedPrefs!!.getBoolean(SettingsFragment.PREFERENCE_THEME, false)
if (mDarkTheme) {
setTheme(R.style.DarkTheme)
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_course)
// mDialog = CourseDialogFragment()
mCourseListRecyclerView = findViewById(R.id.courseRecyclerView)
mCourseDb = CourseDatabase.getInstance(applicationContext)
mCourseListRecyclerView = findViewById(R.id.courseRecyclerView)
val layoutManager: RecyclerView.LayoutManager = LinearLayoutManager(applicationContext)
mCourseListRecyclerView!!.layoutManager = layoutManager
mCourseAdapter = CourseAdapter(loadCourses())
mCourseListRecyclerView!!.adapter = mCourseAdapter
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.course_menu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// handle item selection
return when (item.itemId) {
R.id.settings -> {
// starts the settings fragment
// dummy snackbar for filler until I can get settings done
val intent = Intent(this, SettingsActivity::class.java)
startActivity(intent)
//Snackbar.make(findViewById(android.R.id.content), "*proceeds to make raspberry noises*", 5000).show()
true
}
R.id.edit -> {
// up comes a dialog box editing the desired list item
mDialog = CourseDialogFragment()
mDialog.getContext(CourseContext.EDIT, mCourseDb)
mDialog.show(supportFragmentManager, "")
true
}
R.id.delete -> {
// takes out item.itemId aka deletes record
true
}
else -> super.onOptionsItemSelected(item)
}
}
override fun onCourseEntered(course: String) {
// Returns subject entered in the SubjectDialogFragment dialog
if (course!!.isNotEmpty()) {
val c = Course(course)
if (mCourseDb.addCourse(c)) {
mCourseAdapter?.addCourse(c)
Toast.makeText(this@CourseActivity, course, Toast.LENGTH_LONG).show()
} else {
val message = resources.getString("Already exists!".toInt(), course)
Toast.makeText(this@CourseActivity, message, Toast.LENGTH_SHORT).show()
}
}
}
// click the FAB for days
fun addCourseClick(view: View) {
// brings up dialog to add course
// before that, though, we have pass the course context so we know what has to happen to the dialog
mDialog = CourseDialogFragment()
mDialog.getContext(CourseContext.ADD, mCourseDb)
mDialog.show(supportFragmentManager, "")
}
private fun loadCourses() : MutableList<Course> {
return mCourseDb.getCourses()
}
private inner class CourseHolder(inflater: LayoutInflater, parent: ViewGroup?) : RecyclerView.ViewHolder(inflater.inflate(R.layout.recycler_view_items, parent, false)), View.OnClickListener, View.OnLongClickListener {
private var mCourse: Course? = null
private val mTextView: TextView
fun bind(course: Course) {
mCourse = course
mTextView.text = course.name
mTextView.setBackgroundColor(Color.RED)
}
override fun onClick(view: View) {
// Start QuestionActivity, indicating what subject was clicked
mDialog = CourseDialogFragment()
mDialog.getContext(CourseContext.VIEW, mCourseDb)
mDialog.show(supportFragmentManager, "")
}
override fun onLongClick(view: View?): Boolean {
if (mActionMode != null) {
return false
}
mSelectedCourse = mCourse!!
mSelectedCoursePosition = adapterPosition
// Re-bind the selected item
mCourseAdapter?.notifyItemChanged(mSelectedCoursePosition)
// Show the CAB
mActionMode = this@CourseActivity.startActionMode(mActionModeCallback)!!
return true
}
private val mActionModeCallback: ActionMode.Callback = object : ActionMode.Callback {
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
// Provide context menu for CAB
val inflater = mode.menuInflater
inflater.inflate(R.menu.context_menu, menu)
return true
}
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
return false
}
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
// Process action item selection
return when (item.getItemId()) {
R.id.delete -> {
// Delete from the database and remove from the RecyclerView
mCourseDb.deleteCourse(mSelectedCourse)
mCourseAdapter?.removeCourse(mSelectedCourse)
// Close the CAB
mode.finish()
true
}
else -> false
}
}
override fun onDestroyActionMode(mode: ActionMode) {
//mActionMode = null
// CAB closing, need to deselect item if not deleted
mCourseAdapter?.notifyItemChanged(mSelectedCoursePosition)
mSelectedCoursePosition = RecyclerView.NO_POSITION
}
}
init {
itemView.setOnClickListener(this)
itemView.setOnLongClickListener(this)
mTextView = itemView.findViewById(R.id.courseTextView)
}
}
private inner class CourseAdapter(private val mCourseList: MutableList<Course>) : RecyclerView.Adapter<CourseHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CourseHolder {
val layoutInflater = LayoutInflater.from(applicationContext)
return CourseHolder(layoutInflater, parent)
}
override fun onBindViewHolder(holder: CourseHolder, position: Int) {
holder.bind(mCourseList[position])
}
override fun getItemCount(): Int {
return mCourseList.size
}
fun removeCourse(course: Course?) {
// Find subject in the list
val index = mCourseList.indexOf(course)
if (index >= 0) {
// Remove the subject
mCourseList.removeAt(index)
// Notify adapter of subject removal
notifyItemRemoved(index)
}
}
fun addCourse(course: Course?) {
// Add the new subject at the beginning of the list
mCourseList.add(0, course!!)
// Notify the adapter that item was added to the beginning of the list
notifyItemInserted(0)
// Scroll to the top
mCourseListRecyclerView?.scrollToPosition(0)
}
}
}

View File

@ -0,0 +1,8 @@
package com.wyattjmiller.classscheduleapp
enum class CourseContext {
ADD,
EDIT,
VIEW,
DELETE
}

View File

@ -4,28 +4,20 @@ import android.content.ContentValues
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.os.Build
import java.util.ArrayList
import java.util.*
class CourseDatabase private constructor(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, VERSION) {
class CourseDatabase(context: Context?) : SQLiteOpenHelper(context, DATABASE_NAME, null, VERSION) {
override fun onCreate(db: SQLiteDatabase) {
db.execSQL(
"create table " + CourseTable.TABLE + " (" +
CourseTable.COL_ID + " primary key autoincrement, " +
CourseTable.COL_NAME + " int, " +
CourseTable.COL_DESCRIPTION + " string, " +
CourseTable.COL_LOCATION + " string, " +
CourseTable.COL_DAYOFWEEK + " string, " +
CourseTable.COL_TIME + " string, " +
CourseTable.COL_INSTRUCTOR + " string, " +
CourseTable.COL_UPDATE_TIME + " int)"
CourseTable.COL_ID + " integer primary key autoincrement, " +
CourseTable.COL_NAME + " text, " +
CourseTable.COL_DESCRIPTION + " text, " +
CourseTable.COL_LOCATION + " text, " +
CourseTable.COL_DAYOFWEEK + " text, " +
CourseTable.COL_TIME + " text, " +
CourseTable.COL_INSTRUCTOR + " text) "
)
val course = Course()
val values = ContentValues()
values.put(CourseTable.COL_NAME, course.name)
db.insert(CourseTable.TABLE, null, values)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
@ -35,31 +27,27 @@ class CourseDatabase private constructor(context: Context) : SQLiteOpenHelper(co
override fun onOpen(db: SQLiteDatabase) {
super.onOpen(db)
if (!db.isReadOnly) {
// Enable foreign key constraints
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
db.execSQL("pragma foreign_keys = on;")
} else {
db.setForeignKeyConstraintsEnabled(true)
}
db.setForeignKeyConstraintsEnabled(true)
}
}
fun getCourses(course: String): List<Course> {
fun getCourses(): MutableList<Course> {
val courses: MutableList<Course> = ArrayList<Course>()
val db = this.readableDatabase
val sql = ("select * from " + CourseTable.TABLE)
val cursor = db.rawQuery(sql, arrayOf(course))
val sql =
"select * from " + CourseTable.TABLE
val cursor = db.rawQuery(sql, null)
if (cursor.moveToFirst()) {
do {
val course = Course()
course.id = cursor.getLong(0)
course.id = cursor.getInt(0)
course.name = cursor.getString(1)
course.description = cursor.getString(2)
course.location = cursor.getString(3)
course.dayOfWeek = cursor.getString(4)
course.dayofweek = cursor.getString(4)
course.time = cursor.getString(5)
course.instructor = cursor.getString(6)
courses.add(course)
@ -70,78 +58,64 @@ class CourseDatabase private constructor(context: Context) : SQLiteOpenHelper(co
return courses
}
fun getCourse(questionId: Long): Course? {
var course: Course? = null
fun getCourse(courseId: Long): Course {
val course = Course()
val db = this.readableDatabase
val sql = ("select * from " + CourseTable.TABLE +
" where " + CourseTable.COL_ID + " = ?")
val cursor = db.rawQuery(sql, arrayOf(java.lang.Float.toString(questionId.toFloat())))
val sql
= "select * from " + CourseTable.TABLE +
"where " + CourseTable.COL_ID + " = ?"
val cursor = db.rawQuery(sql, arrayOf(courseId.toString()))
if (cursor.moveToFirst()) {
course?.id = cursor.getLong(0)
course?.name = cursor.getString(1)
course?.description = cursor.getString(2)
course?.location = cursor.getString(3)
course?.dayOfWeek = cursor.getString(4)
course?.time = cursor.getString(5)
course?.instructor = cursor.getString(6)
course.name = cursor.getString(1)
course.description = cursor.getString(2)
course.location = cursor.getString(3)
course.dayofweek = cursor.getString(4)
course.time = cursor.getString(5)
course.instructor = cursor.getString(6)
}
cursor.close()
return course
}
fun addCourse(course: Course) {
fun addCourse(course: Course): Boolean {
val db = writableDatabase
val values = ContentValues()
values.put(CourseTable.COL_NAME, course.name)
values.put(CourseTable.COL_DESCRIPTION, course.description)
values.put(CourseTable.COL_LOCATION, course.location)
values.put(CourseTable.COL_DAYOFWEEK, course.dayOfWeek)
values.put(CourseTable.COL_DAYOFWEEK, course.dayofweek)
values.put(CourseTable.COL_TIME, course.time)
values.put(CourseTable.COL_INSTRUCTOR, course.instructor)
val courseId = db.insert(CourseTable.TABLE, null, values)
course.id = courseId
val id = db.insert(CourseTable.TABLE, null, values)
return id != -1L
}
fun updateCourse(course: Course) {
val db = writableDatabase
val values = ContentValues()
values.put(CourseTable.COL_ID, course.id)
values.put(CourseTable.COL_NAME, course.name)
values.put(CourseTable.COL_DESCRIPTION, course.description)
values.put(CourseTable.COL_LOCATION, course.location)
values.put(CourseTable.COL_DAYOFWEEK, course.dayOfWeek)
values.put(CourseTable.COL_TIME, course.time)
values.put(CourseTable.COL_INSTRUCTOR, course.instructor)
db.update(
CourseTable.TABLE, values,
CourseTable.COL_ID + " = " + course.id, null
)
db.update(CourseTable.TABLE, values, CourseTable.COL_NAME + " = ?", arrayOf(course.name))
}
fun deleteCourse(courseId: Long) {
fun deleteCourse(course: Course) {
val db = writableDatabase
db.delete(
CourseTable.TABLE,
CourseTable.COL_ID + " = " + courseId, null
)
db.delete(CourseTable.TABLE, CourseTable.COL_NAME + " = ?", arrayOf(course.name))
}
companion object {
private val VERSION = 1
private val DATABASE_NAME = "study.db"
private var mStudyDb: CourseDatabase? = null
private const val DATABASE_NAME = "courses.db"
private const val VERSION = 1
private var mCourseDb: CourseDatabase? = null
fun getInstance(context: Context): CourseDatabase? {
if (mStudyDb == null) {
mStudyDb = CourseDatabase(context)
fun getInstance(context: Context?): CourseDatabase {
if (mCourseDb == null) {
mCourseDb = CourseDatabase(context)
}
return mStudyDb
return mCourseDb!!
}
}
}

View File

@ -0,0 +1,124 @@
package com.wyattjmiller.classscheduleapp
import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
class CourseDialogFragment : DialogFragment() {
private lateinit var mTextViewTitle: TextView
private lateinit var mEditTextCourseName: EditText
private lateinit var mEditTextCourseInstructor: EditText
private lateinit var mEditTextCourseLocation: EditText
private lateinit var mEditTextDayOfWeek: EditText
private lateinit var mEditTextCourseTime: EditText
private lateinit var mEditTextCourseDescription: EditText
private lateinit var mContext: CourseContext
private lateinit var mCourseDb: CourseDatabase
private var mCourse: Course = Course()
interface onCourseEnteredListener {
fun onCourseEntered(course: String)
}
private lateinit var mDoneButton: Button
private var mListener: onCourseEnteredListener? = null
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = AlertDialog.Builder(this.activity!!)
val dialogView = activity!!.layoutInflater.inflate(R.layout.dialog_course, null)
mDoneButton = dialogView.findViewById(R.id.buttonFinish)
mTextViewTitle = dialogView.findViewById(R.id.textViewTitle)
mEditTextCourseName = dialogView.findViewById(R.id.editTextCourseName)
mEditTextCourseLocation = dialogView.findViewById(R.id.editTextCourseLocation)
mEditTextCourseInstructor = dialogView.findViewById(R.id.editTextCourseInstructor)
mEditTextDayOfWeek = dialogView.findViewById(R.id.editTextCourseDayOfWeek)
mEditTextCourseTime = dialogView.findViewById(R.id.editTextCourseTime)
mEditTextCourseDescription = dialogView.findViewById(R.id.editTextCourseDescription)
when (mContext) {
CourseContext.ADD -> {
// TODO: set title to add course and when pressing done, add to database
}
CourseContext.EDIT -> {
// TODO: set title to edit course and when pressing done, modify record to database
}
CourseContext.VIEW -> {
// TODO: set title to view course, make everything text, and when pressing done, close dialog
}
}
builder.setView(dialogView)
mDoneButton.setOnClickListener {
when (mContext) {
CourseContext.ADD -> {
mCourse.name = mEditTextCourseName.text.toString()
mCourse.description = mEditTextCourseDescription.text.toString()
mCourse.location = mEditTextCourseLocation.text.toString()
mCourse.dayofweek = mEditTextDayOfWeek.text.toString()
mCourse.time = mEditTextCourseTime.text.toString()
mCourse.instructor = mEditTextCourseInstructor.text.toString()
val valid = this.validityCheck()
if (valid) {
val course = mCourse.name
mListener?.onCourseEntered(course!!.trim())
dismiss()
}
}
CourseContext.EDIT -> {
mCourse.name = mEditTextCourseName.text.toString()
mCourse.description = mEditTextCourseDescription.text.toString()
mCourse.location = mEditTextCourseLocation.text.toString()
mCourse.dayofweek = mEditTextDayOfWeek.text.toString()
mCourse.time = mEditTextCourseTime.text.toString()
mCourse.instructor = mEditTextCourseInstructor.text.toString()
val valid = this.validityCheck()
if (valid) {
val course = mCourse.name
mListener?.onCourseEntered(course!!.trim())
dismiss()
}
}
CourseContext.VIEW -> {
dismiss()
}
}
}
return builder.create()
}
fun getContext(context: CourseContext, database: CourseDatabase) {
mContext = context
mCourseDb = database
}
override fun onAttach(context: Context) {
super.onAttach(context)
mListener = context as onCourseEnteredListener
}
private fun validityCheck() : Boolean {
return if (mEditTextCourseName.text.toString() == "" || mEditTextCourseLocation.text.toString() == "" || mEditTextDayOfWeek.text.toString() == ""
|| mEditTextCourseTime.text.toString() == "" || mEditTextCourseInstructor.text.toString() == "" || mEditTextCourseDescription.text.toString() == "") {
Toast.makeText(this.activity!!, "Please fill in all of the fields", Toast.LENGTH_LONG).show()
false
} else {
true
}
}
companion object {
const val EXTRA_COURSE_ID = "com.wyattjmiller.classscheduleapp.course_id"
}
}

View File

@ -1,13 +1,12 @@
package com.wyattjmiller.classscheduleapp
object CourseTable {
val TABLE = "class"
val COL_ID = "_id"
val COL_NAME = "name"
val COL_DESCRIPTION = "description"
val COL_LOCATION = "location"
val COL_DAYOFWEEK = "dayofweek"
val COL_TIME = "time"
val COL_INSTRUCTOR = "instructor"
val COL_UPDATE_TIME = "updated"
const val TABLE = "course"
const val COL_ID = "_id"
const val COL_NAME = "name"
const val COL_DESCRIPTION = "description"
const val COL_LOCATION = "location"
const val COL_DAYOFWEEK = "dayofweek"
const val COL_TIME = "time"
const val COL_INSTRUCTOR = "instructor"
}

View File

@ -1,11 +0,0 @@
package com.wyattjmiller.classscheduleapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}

View File

@ -0,0 +1,18 @@
package com.wyattjmiller.classscheduleapp;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
public class SettingsActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display the fragment as the main content
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
}
}

View File

@ -0,0 +1,50 @@
package com.wyattjmiller.classscheduleapp;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
public class SettingsFragment extends PreferenceFragment {
public static String PREFERENCE_THEME = "pref_theme";
public static String PREFERENCE_SUBJECT_ORDER = "pref_subject_order";
public static String PREFERENCE_DEFAULT_QUESTION = "pref_default_question";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
// Access the default shared prefs
SharedPreferences sharedPrefs =
PreferenceManager.getDefaultSharedPreferences(getActivity());
setPrefSummarySubjectOrder(sharedPrefs);
setPrefSummaryDefaultQuestion(sharedPrefs);
}
// Set the summary to the currently selected subject order
private void setPrefSummarySubjectOrder(SharedPreferences sharedPrefs) {
String order = sharedPrefs.getString(PREFERENCE_SUBJECT_ORDER, "1");
String[] subjectOrders = getResources().getStringArray(R.array.pref_subject_order);
Preference subjectOrderPref = findPreference(PREFERENCE_SUBJECT_ORDER);
subjectOrderPref.setSummary(subjectOrders[Integer.parseInt(order)]);
}
// Set the summary to the default question
private void setPrefSummaryDefaultQuestion(SharedPreferences sharedPrefs) {
String defaultQuestion = sharedPrefs.getString(PREFERENCE_DEFAULT_QUESTION, "");
defaultQuestion = defaultQuestion.trim();
Preference questionPref = findPreference(PREFERENCE_DEFAULT_QUESTION);
if (defaultQuestion.length() == 0) {
questionPref.setSummary(getResources().getString(R.string.pref_none));
}
else {
questionPref.setSummary(defaultQuestion);
}
}
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>

View File

@ -0,0 +1,11 @@
<!-- drawable/delete.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z"/>
</vector>

View File

@ -0,0 +1,26 @@
<?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"
tools:context=".CourseActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/courseRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/addCourseButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="addCourseClick"
android:layout_gravity="end|bottom"
app:srcCompat="@drawable/add"
android:layout_margin="16dp" />
</FrameLayout>

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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">
<TextView
android:id="@+id/textViewCourseName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="Name"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/editTextCourseName"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewTitle"
app:layout_constraintVertical_bias="0.059" />
<EditText
android:id="@+id/editTextCourseName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewTitle" />
<TextView
android:id="@+id/textViewTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Course Dialog"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textViewCourseLocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="44dp"
android:text="Location"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewCourseName" />
<EditText
android:id="@+id/editTextCourseLocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editTextCourseName" />
<EditText
android:id="@+id/editTextCourseDayOfWeek"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editTextCourseLocation" />
<TextView
android:id="@+id/textViewCourseDayOfWeek"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="44dp"
android:text="Day of Week"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewCourseLocation" />
<TextView
android:id="@+id/textViewCourseTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="44dp"
android:text="Time"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewCourseDayOfWeek" />
<EditText
android:id="@+id/editTextCourseTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:inputType="time"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editTextCourseDayOfWeek" />
<TextView
android:id="@+id/textViewCourseInstructor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="44dp"
android:text="Instructor"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewCourseTime" />
<EditText
android:id="@+id/editTextCourseInstructor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editTextCourseTime" />
<Button
android:id="@+id/buttonFinish"
android:layout_width="246dp"
android:layout_height="44dp"
android:layout_marginBottom="16dp"
android:onClick="onClickFinish"
android:text="Done"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.496"
app:layout_constraintStart_toStartOf="parent" />
<EditText
android:id="@+id/editTextCourseDescription"
android:layout_width="327dp"
android:layout_height="135dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:gravity="start|top"
android:inputType="textMultiLine"
app:layout_constraintBottom_toTopOf="@+id/buttonFinish"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.461"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewCourseDescription"
app:layout_constraintVertical_bias="0.087" />
<TextView
android:id="@+id/textViewCourseDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="36dp"
android:text="Description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.058"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewCourseInstructor" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardview1"
android:layout_width="match_parent"
android:layout_height="150dp"
card_view:cardCornerRadius="5dp"
card_view:cardUseCompatPadding="true">
<TextView
android:id="@+id/courseTextView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="#000"
android:padding="10dp"
android:layout_gravity="center"
android:gravity="center" />
</androidx.cardview.widget.CardView>

View File

@ -0,0 +1,17 @@
<?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/delete"
android:title="@string/delete"
android:icon="@drawable/delete"
app:showAsAction="ifRoom">
</item>
<item android:id="@+id/edit"
android:title="@string/edit"
android:icon="@drawable/edit"
app:showAsAction="ifRoom">
</item>
</menu>

View File

@ -0,0 +1,10 @@
<?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/settings"
android:icon="@drawable/settings"
android:title="@string/settings"
app:showAsAction="ifRoom"/>
</menu>

View File

@ -3,4 +3,10 @@
<color name="colorPrimary">#6200EE</color>
<color name="colorPrimaryDark">#3700B3</color>
<color name="colorAccent">#03DAC5</color>
<color name="colorBackgroundDark">#000</color>
<color name="colorAppBar">#023</color>
<color name="colorText">#BBB</color>
<color name="colorTextSecondary">#999</color>
<color name="colorButton">#555</color>
</resources>

View File

@ -1,3 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">ClassScheduleApp</string>
<string name="app_name">Class Scheduler</string>
<string name="previous">Previous</string>
<string name="next">Next</string>
<string name="add">Add</string>
<string name="delete">Delete</string>
<string name="edit">Edit</string>
<string name="update">Update</string>
<string name="course_deleted">Class deleted.</string>
<string name="course_added">Class added.</string>
<string name="course_updated">Class updated.</string>
<string name="create">Create</string>
<string name="course">New class?</string>
<string name="name">Name</string>
<string name="descripition">Description</string>
<string name="location">Location</string>
<string name="dayofweek">Day of Week</string>
<string name="time">Time</string>
<string name="instructor">Instructor</string>
<string name="cancel">Cancel</string>
<string name="update_course">Update Class</string>
<string name="add_course">Add Class</string>
<string name="no_courses">No classes exist for this subject.</string>
<string name="course_exists">The class "%1$s" already exists.</string>
<string name="course_number">%1$s (%2$d of %3$d)</string>
<string name="select_course">Select a class:</string>
<string name="undo">Undo</string>
<string name="settings">Settings</string>
<string name="pref_title_theme">Dark theme</string>
<string name="pref_description_theme">Turn on dark theme</string>
<string name="pref_title_default_question">Default question</string>
<string name="pref_title_subject_order">Subject order</string>
<string name="pref_none">None</string>
<string-array name="pref_subject_order">
<item>Alphabetic</item>
<item>Most recent first</item>
<item>Oldest first</item>
</string-array>
<string-array name="pref_subject_order_values">
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
</resources>

View File

@ -7,4 +7,14 @@
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="DarkTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorAppBar</item>
<item name="colorPrimaryDark">@color/colorBackgroundDark</item>
<item name="colorAccent">@color/colorPrimaryDark</item>
<item name="android:colorBackground">@color/colorBackgroundDark</item>
<item name="android:textColor">@color/colorText</item>
<item name="android:textColorSecondary">@color/colorTextSecondary</item>
<item name="android:editTextColor">@color/colorText</item>
<item name="colorButtonNormal">@color/colorButton</item>
</style>
</resources>

View File

@ -0,0 +1,26 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<SwitchPreference
android:defaultValue="false"
android:key="pref_theme"
android:title="@string/pref_title_theme"
android:summary="@string/pref_description_theme" />
<ListPreference
android:defaultValue="1"
android:entries="@array/pref_subject_order"
android:entryValues="@array/pref_subject_order_values"
android:key="pref_subject_order"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="@string/pref_title_subject_order" />
<EditTextPreference
android:key="pref_default_question"
android:inputType="text"
android:maxLines="1"
android:selectAllOnFocus="true"
android:title="@string/pref_title_default_question" />
</PreferenceScreen>

View File

@ -6,7 +6,7 @@ buildscript {
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.1"
classpath 'com.android.tools.build:gradle:4.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong