diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/AddButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/AddButtonView.kt index fb7885fea..0034d2b94 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/AddButtonView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/AddButtonView.kt @@ -47,7 +47,7 @@ class AddButtonView( private inner class Drawer { private val rect = RectF() - private val highContrastColor = sres.getColor(R.attr.contrast100) + private val highContrastColor = sres.getColor(R.attr.contrast80) private val paint = TextPaint().apply { typeface = getFontAwesome() diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CollapseButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CollapseButtonView.kt new file mode 100644 index 000000000..12c54cf55 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CollapseButtonView.kt @@ -0,0 +1,101 @@ +package org.isoron.uhabits.activities.habits.list.views + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.RectF +import android.text.TextPaint +import android.view.View +import org.isoron.uhabits.R +import org.isoron.uhabits.activities.habits.list.ListHabitsActivity +import org.isoron.uhabits.core.models.HabitGroup +import org.isoron.uhabits.core.models.ModelObservable +import org.isoron.uhabits.utils.getFontAwesome +import org.isoron.uhabits.utils.sp +import org.isoron.uhabits.utils.sres +import org.isoron.uhabits.utils.toMeasureSpec + +class CollapseButtonView( + context: Context, + var habitGroup: HabitGroup? +) : View(context), + View.OnClickListener, + ModelObservable.Listener { + + private var drawer = Drawer() + + var collapsed = false + + init { + setOnClickListener(this) + } + + override fun onClick(v: View) { + collapsed = !collapsed + habitGroup!!.collapsed = collapsed + drawer.rotate() + invalidate() + (context as ListHabitsActivity).component.listHabitsMenu.behavior.onPreferencesChanged() + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + drawer.draw(canvas) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val height = resources.getDimensionPixelSize(R.dimen.checkmarkHeight) + val width = resources.getDimensionPixelSize(R.dimen.checkmarkWidth) + super.onMeasure( + width.toMeasureSpec(MeasureSpec.EXACTLY), + height.toMeasureSpec(MeasureSpec.EXACTLY) + ) + } + + private inner class Drawer { + private val rect = RectF() + private val highContrastColor = sres.getColor(R.attr.contrast100) + + private var rotationAngle = 0f + private var offset_y = 0.4f + private var offset_x = 0f + private val paint = TextPaint().apply { + typeface = getFontAwesome() + isAntiAlias = true + textAlign = Paint.Align.CENTER + } + + fun rotate() { + if (rotationAngle == 0f) { + rotationAngle = 90f + offset_y = 0f + offset_x = -0.4f + } else { + rotationAngle = 0f + offset_y = 0.4f + offset_x = 0f + } + } + + fun draw(canvas: Canvas) { + paint.color = highContrastColor + val id = R.string.fa_angle_down + paint.textSize = sp(12.0f) + paint.strokeWidth = 0f + paint.style = Paint.Style.FILL + + val label = resources.getString(id) + val em = paint.measureText("m") + + rect.set(0f, 0f, width.toFloat(), height.toFloat()) + rect.offset(offset_x * em, offset_y * em) + + canvas.save() // Save the current state of the canvas + canvas.rotate(rotationAngle, rect.centerX(), rect.centerY()) // Rotate the canvas + canvas.drawText(label, rect.centerX(), rect.centerY(), paint) + canvas.restore() + } + } + + override fun onModelChange() {} +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitGroupCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitGroupCardView.kt index 4bbffa7e2..bcac0dafa 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitGroupCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitGroupCardView.kt @@ -42,6 +42,7 @@ class HabitGroupCardView( field = newHabitGroup if (newHabitGroup != null) copyAttributesFrom(newHabitGroup) addButtonView.habitGroup = newHabitGroup + collapseButtonView.habitGroup = newHabitGroup } var score @@ -52,6 +53,7 @@ class HabitGroupCardView( } var addButtonView: AddButtonView + var collapseButtonView: CollapseButtonView private var innerFrame: LinearLayout private var label: TextView private var scoreRing: RingView @@ -81,6 +83,7 @@ class HabitGroupCardView( } addButtonView = AddButtonView(context, habitGroup) + collapseButtonView = CollapseButtonView(context, habitGroup) innerFrame = LinearLayout(context).apply { gravity = Gravity.CENTER_VERTICAL @@ -91,6 +94,7 @@ class HabitGroupCardView( addView(scoreRing) addView(label) addView(addButtonView) + addView(collapseButtonView) setOnTouchListener { v, event -> v.background.setHotspot(event.x, event.y) @@ -142,6 +146,12 @@ class HabitGroupCardView( scoreRing.apply { setColor(c) } + + if (collapseButtonView.collapsed) { + addButtonView.visibility = GONE + } else { + addButtonView.visibility = VISIBLE + } } private fun updateBackground(isSelected: Boolean) { diff --git a/uhabits-android/src/main/res/values/fontawesome.xml b/uhabits-android/src/main/res/values/fontawesome.xml index 53e20cc46..6586f31c9 100644 --- a/uhabits-android/src/main/res/values/fontawesome.xml +++ b/uhabits-android/src/main/res/values/fontawesome.xml @@ -25,6 +25,8 @@ + + diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt index 8a0c1a17c..332466625 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt @@ -56,6 +56,8 @@ data class Habit( val uriString: String get() = "content://org.isoron.uhabits/habit/$id" + var collapsed = false + fun isSubHabit(): Boolean = groupUUID != null fun hasReminder(): Boolean = reminder != null diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/HabitGroup.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/HabitGroup.kt index d08ea3e3a..be2ef7365 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/HabitGroup.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/HabitGroup.kt @@ -45,6 +45,14 @@ data class HabitGroup( val uriString: String get() = "content://org.isoron.uhabits/habitgroup/$id" + var collapsed = false + set(value) { + if (value != field) { + field = value + habitList.forEach { it.collapsed = value } + } + } + fun hasReminder(): Boolean = reminder != null fun isCompletedToday(): Boolean { diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/HabitMatcher.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/HabitMatcher.kt index fbfedb3e0..4ef35087d 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/HabitMatcher.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/HabitMatcher.kt @@ -29,6 +29,7 @@ data class HabitMatcher( if (isReminderRequired && !habit.hasReminder()) return false if (!isCompletedAllowed && habit.isCompletedToday()) return false if (!isEnteredAllowed && habit.isEnteredToday()) return false + if (habit.collapsed) return false return true } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/memory/MemoryHabitGroupList.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/memory/MemoryHabitGroupList.kt index b9aa7a71e..4fef8519c 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/memory/MemoryHabitGroupList.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/memory/MemoryHabitGroupList.kt @@ -47,6 +47,7 @@ class MemoryHabitGroupList : HabitGroupList { parent.observable.addListener { loadFromParent() } for (hgr in parent.list) { hgr.habitList.observable.addListener { loadFromParent() } + hgr.observable.notifyListeners() } loadFromParent() }