diff --git a/android/uhabits-android/src/main/AndroidManifest.xml b/android/uhabits-android/src/main/AndroidManifest.xml index 13d637217..904b5bb9c 100644 --- a/android/uhabits-android/src/main/AndroidManifest.xml +++ b/android/uhabits-android/src/main/AndroidManifest.xml @@ -136,6 +136,18 @@ android:resource="@xml/widget_checkmark_info" /> + + + + + + + + + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +package org.isoron.uhabits.widgets + +import android.app.* +import android.content.* +import android.view.* +import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.utils.* +import org.isoron.uhabits.widgets.views.* + +open class CheckmarkWidgetWithTime( + context: Context, + widgetId: Int, + protected val habit: Habit +) : BaseWidget(context, widgetId) { + + override fun getOnClickPendingIntent(context: Context): PendingIntent { + return if (habit.isNumerical) { + pendingIntentFactory.setNumericalValue(context, habit, 10, null) + } else { + pendingIntentFactory.toggleCheckmark(habit, null) + } + } + + override fun refreshData(v: View) { + (v as CheckmarkTimeWidgetView).apply { + setBackgroundAlpha(preferedBackgroundAlpha) + + setActiveColor(PaletteUtils.getColor(context, habit.color)) + setName(habit.name) + setCheckmarkValue(habit.checkmarks.todayValue) + if (habit.isNumerical) { + setNumerical(true) + setCheckmarkState(getNumericalCheckmarkState()) + } else { + setCheckmarkState(habit.checkmarks.todayValue) + } + setPercentage(habit.scores.todayValue.toFloat()) + refresh() + } + } + + override fun buildView(): View { + return CheckmarkTimeWidgetView(context) + } + + override fun getDefaultHeight() = 125 + override fun getDefaultWidth() = 125 + + private fun getNumericalCheckmarkState(): Int { + return if (habit.isCompletedToday) { + Checkmark.CHECKED_EXPLICITLY + } else { + Checkmark.UNCHECKED + } + } + +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidgetWithTimeProvider.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidgetWithTimeProvider.kt new file mode 100644 index 000000000..69955a6ca --- /dev/null +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidgetWithTimeProvider.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ +package org.isoron.uhabits.widgets + +import android.content.* + +class CheckmarkWidgetWithTimeProvider : BaseWidgetProvider() { + override fun getWidgetFromId(context: Context, id: Int): BaseWidget { + val habits = getHabitsFromWidgetId(id) + if (habits.size == 1) return CheckmarkWidgetWithTime(context, id, habits[0]) + else return StackWidget(context, id, StackWidgetType.CHECKMARKTIME, habits) + } +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.java index 7a014f394..998e8757a 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.java @@ -2,6 +2,8 @@ package org.isoron.uhabits.widgets; import org.isoron.uhabits.R; +import java.lang.annotation.Target; + /** * Created by victoryu on 11/3/17. */ @@ -13,7 +15,8 @@ public enum StackWidgetType { SCORE(2), // habit strength widget HISTORY(3), STREAKS(4), - TARGET(5); + TARGET(5), + CHECKMARKTIME(6); private int value; StackWidgetType(int value) { @@ -37,6 +40,8 @@ public enum StackWidgetType { return STREAKS; } else if (TARGET.getValue() == value) { return TARGET; + } else if (CHECKMARKTIME.getValue() == value) { + return CHECKMARKTIME; } return null; } @@ -55,6 +60,8 @@ public enum StackWidgetType { return R.layout.streak_stackview_widget; case TARGET: return R.layout.target_stackview_widget; + case CHECKMARKTIME: + return R.layout.checkmarktime_stackview_widget; } return 0; } @@ -73,6 +80,8 @@ public enum StackWidgetType { return R.id.streakStackWidgetView; case TARGET: return R.id.targetStackWidgetView; + case CHECKMARKTIME: + return R.id.checkmarkTimeStackWidgetView; } return 0; } @@ -91,6 +100,8 @@ public enum StackWidgetType { return R.id.streakStackWidgetEmptyView; case TARGET: return R.id.targetStackWidgetEmptyView; + case CHECKMARKTIME: + return R.id.checkmarkTimeStackWidgetEmptyView; } return 0; } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt index 17d6d5d77..14c383245 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt @@ -68,6 +68,7 @@ class WidgetUpdater updateWidgets(modifiedHabitId, StreakWidgetProvider::class.java) updateWidgets(modifiedHabitId, FrequencyWidgetProvider::class.java) updateWidgets(modifiedHabitId, TargetWidgetProvider::class.java) + updateWidgets(modifiedHabitId, CheckmarkWidgetWithTimeProvider::class.java) } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkTimeWidgetView.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkTimeWidgetView.java new file mode 100644 index 000000000..a0f32ec82 --- /dev/null +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkTimeWidgetView.java @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +package org.isoron.uhabits.widgets.views; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.isoron.androidbase.utils.StyledResources; +import org.isoron.uhabits.R; +import org.isoron.uhabits.activities.common.views.RingView; +import org.isoron.uhabits.activities.habits.list.views.NumberButtonViewKt; +import org.isoron.uhabits.core.models.Checkmark; +import org.isoron.uhabits.utils.PaletteUtils; + +import static org.isoron.androidbase.utils.InterfaceUtils.getDimension; + +public class CheckmarkTimeWidgetView extends HabitWidgetView { + protected int activeColor; + + protected float percentage; + + @Nullable + protected String name; + + protected RingView ring; + + protected TextView label; + + protected int checkmarkValue; + + protected int checkmarkState; + + protected boolean isNumerical; + + public CheckmarkTimeWidgetView(Context context) + { + super(context); + init(); + } + + public CheckmarkTimeWidgetView(Context context, AttributeSet attrs) + { + super(context, attrs); + init(); + } + + public void refresh() + { + if (backgroundPaint == null || frame == null || ring == null) return; + + StyledResources res = new StyledResources(getContext()); + + int bgColor; + int fgColor; + + switch (checkmarkState) { + case Checkmark.CHECKED_EXPLICITLY: + case Checkmark.SKIPPED: + bgColor = activeColor; + fgColor = res.getColor(R.attr.highContrastReverseTextColor); + setShadowAlpha(0x4f); + backgroundPaint.setColor(bgColor); + frame.setBackgroundDrawable(background); + break; + + case Checkmark.CHECKED_IMPLICITLY: + case Checkmark.UNCHECKED: + default: + getResources().getString(R.string.fa_times); + bgColor = res.getColor(R.attr.cardBgColor); + fgColor = res.getColor(R.attr.mediumContrastTextColor); + setShadowAlpha(0x00); + break; + } + + ring.setPercentage(percentage); + ring.setColor(fgColor); + ring.setBackgroundColor(bgColor); + ring.setText(getText()); + + label.setText(name); + label.setTextColor(fgColor); + + requestLayout(); + postInvalidate(); + } + + public void setCheckmarkState(int checkmarkState) + { + this.checkmarkState = checkmarkState; + } + + protected String getText() + { + if (isNumerical) return NumberButtonViewKt.toShortString(checkmarkValue / 1000.0); + switch (checkmarkState) { + case Checkmark.CHECKED_EXPLICITLY: + case Checkmark.CHECKED_IMPLICITLY: + return getResources().getString(R.string.fa_check); + case Checkmark.SKIPPED: + return getResources().getString(R.string.fa_skipped); + case Checkmark.UNCHECKED: + default: + return getResources().getString(R.string.fa_times); + } + } + + public void setActiveColor(int activeColor) + { + this.activeColor = activeColor; + } + + public void setCheckmarkValue(int checkmarkValue) + { + this.checkmarkValue = checkmarkValue; + } + + public void setName(@NonNull String name) + { + this.name = name; + } + + public void setPercentage(float percentage) + { + this.percentage = percentage; + } + + public void setNumerical(boolean isNumerical) + { + this.isNumerical = isNumerical; + } + + @Override + @NonNull + protected Integer getInnerLayoutId() + { + return R.layout.widget_checkmarktime; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) + { + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + + float w = width; + float h = width * 1.25f; + float scale = Math.min(width / w, height / h); + + w *= scale; + h *= scale; + + if (h < getDimension(getContext(), R.dimen.checkmarkWidget_heightBreakpoint)) + ring.setVisibility(GONE); + else + ring.setVisibility(VISIBLE); + + widthMeasureSpec = + MeasureSpec.makeMeasureSpec((int) w, MeasureSpec.EXACTLY); + heightMeasureSpec = + MeasureSpec.makeMeasureSpec((int) h, MeasureSpec.EXACTLY); + + float textSize = 0.15f * h; + float maxTextSize = getDimension(getContext(), R.dimen.smallerTextSize); + textSize = Math.min(textSize, maxTextSize); + + label.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); + ring.setTextSize(textSize); + ring.setThickness(0.15f * textSize); + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + private void init() + { + ring = (RingView) findViewById(R.id.scoreRing); + label = (TextView) findViewById(R.id.label); + + if (ring != null) ring.setIsTransparencyEnabled(true); + + if (isInEditMode()) + { + percentage = 0.75f; + name = "Wake up early"; + activeColor = PaletteUtils.getAndroidTestColor(6); + checkmarkValue = Checkmark.CHECKED_EXPLICITLY; + refresh(); + } + } +} diff --git a/android/uhabits-android/src/main/res/layout/checkmarktime_stackview_widget.xml b/android/uhabits-android/src/main/res/layout/checkmarktime_stackview_widget.xml new file mode 100644 index 000000000..9547321b4 --- /dev/null +++ b/android/uhabits-android/src/main/res/layout/checkmarktime_stackview_widget.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/android/uhabits-android/src/main/res/layout/widget_checkmarktime.xml b/android/uhabits-android/src/main/res/layout/widget_checkmarktime.xml new file mode 100644 index 000000000..90a36d2b3 --- /dev/null +++ b/android/uhabits-android/src/main/res/layout/widget_checkmarktime.xml @@ -0,0 +1,60 @@ + + + + + + + + + + \ No newline at end of file diff --git a/android/uhabits-android/src/main/res/xml/widget_checkmarktime_info.xml b/android/uhabits-android/src/main/res/xml/widget_checkmarktime_info.xml new file mode 100644 index 000000000..5e988f548 --- /dev/null +++ b/android/uhabits-android/src/main/res/xml/widget_checkmarktime_info.xml @@ -0,0 +1,30 @@ + + + + + \ No newline at end of file