Create target widget

pull/605/head
Alinson S. Xavier 5 years ago
parent a6060f468d
commit 40bc35935f

@ -17,8 +17,8 @@
android:theme="@style/AppBaseTheme">
<activity
android:exported="true"
android:name=".activities.habits.edit.EditHabitActivity">
android:name=".activities.habits.edit.EditHabitActivity"
android:exported="true">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.habits.list.ListHabitsActivity" />
@ -53,6 +53,7 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.habits.list.ListHabitsActivity" />
</activity>
<activity
android:name=".activities.settings.SettingsActivity"
android:label="@string/settings">
@ -60,10 +61,12 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.habits.list.ListHabitsActivity" />
</activity>
<activity
android:name=".activities.intro.IntroActivity"
android:label=""
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
<activity
android:name=".widgets.HabitPickerDialog"
android:theme="@style/Theme.AppCompat.Light.Dialog">
@ -71,6 +74,7 @@
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
<activity
android:name=".activities.about.AboutActivity"
android:label="@string/about">
@ -78,11 +82,12 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.habits.list.ListHabitsActivity" />
</activity>
<activity
android:name=".notifications.SnoozeDelayPickerActivity"
android:excludeFromRecents="true"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity>
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
<receiver
android:name=".widgets.CheckmarkWidgetProvider"
@ -112,6 +117,7 @@
android:name="android.appwidget.provider"
android:resource="@xml/widget_history_info" />
</receiver>
<receiver
android:name=".widgets.ScoreWidgetProvider"
android:label="@string/habit_strength">
@ -123,6 +129,7 @@
android:name="android.appwidget.provider"
android:resource="@xml/widget_score_info" />
</receiver>
<receiver
android:name=".widgets.StreakWidgetProvider"
android:label="@string/streaks">
@ -134,6 +141,7 @@
android:name="android.appwidget.provider"
android:resource="@xml/widget_streak_info" />
</receiver>
<receiver
android:name=".widgets.FrequencyWidgetProvider"
android:label="@string/frequency">
@ -145,11 +153,25 @@
android:name="android.appwidget.provider"
android:resource="@xml/widget_frequency_info" />
</receiver>
<receiver
android:name=".widgets.TargetWidgetProvider"
android:label="@string/target">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_frequency_info" />
</receiver>
<receiver android:name=".receivers.ReminderReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".receivers.WidgetReceiver">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
@ -178,7 +200,9 @@
android:host="org.isoron.uhabits"
android:scheme="content" />
</intent-filter>
</receiver> <!-- Locale/Tasker -->
</receiver>
<!-- Locale/Tasker -->
<activity
android:name=".automation.EditSettingActivity"
android:exported="true"
@ -187,7 +211,9 @@
<intent-filter>
<action android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING" />
</intent-filter>
</activity> <!-- Locale/Tasker -->
</activity>
<!-- Locale/Tasker -->
<receiver
android:name=".automation.FireSettingReceiver"
android:exported="true">
@ -209,7 +235,8 @@
<service
android:name=".sync.SyncService"
android:enabled="true"
android:exported="false"></service>
android:exported="false" />
</application>
</manifest>

@ -93,7 +93,8 @@ public class TargetChart extends View
maxLabelSize = Math.max(maxLabelSize, len);
}
rect.set(0, 0, getWidth(), baseSize);
float marginTop = (getHeight() - baseSize * labels.size()) / 2.0f;
rect.set(0, marginTop, getWidth(), marginTop + baseSize);
for (int i = 0; i < labels.size(); i++) {
drawRow(canvas, i, rect);
rect.offset(0, baseSize);
@ -103,8 +104,17 @@ public class TargetChart extends View
@Override
protected void onMeasure(int widthSpec, int heightSpec)
{
baseSize = getResources().getDimensionPixelSize(R.dimen.baseSize);
int width = getSize(widthSpec);
int height = labels.size() * baseSize;
ViewGroup.LayoutParams params = getLayoutParams();
if (params != null && params.height == ViewGroup.LayoutParams.MATCH_PARENT) {
height = getSize(heightSpec);
if (labels.size() > 0) baseSize = height / labels.size();
}
heightSpec = makeMeasureSpec(height, EXACTLY);
widthSpec = makeMeasureSpec(width, EXACTLY);
setMeasuredDimension(widthSpec, heightSpec);
@ -194,7 +204,6 @@ public class TargetChart extends View
mediumContrastTextColor = res.getColor(R.attr.mediumContrastTextColor);
highContrastReverseTextColor = res.getColor(R.attr.highContrastReverseTextColor);
tinyTextSize = getDimension(getContext(), R.dimen.tinyTextSize);
baseSize = getResources().getDimensionPixelSize(R.dimen.baseSize);
}
public void setValues(List<Double> values)

@ -24,6 +24,8 @@ import android.content.res.*;
import android.util.*;
import android.widget.*;
import androidx.annotation.*;
import org.isoron.uhabits.R;
import org.isoron.uhabits.*;
import org.isoron.uhabits.activities.common.views.*;
@ -86,10 +88,10 @@ public class TargetCard extends HabitCard
@Override
protected Task createRefreshTask()
{
return new RefreshTask();
return new RefreshTask(getContext(), getHabit(), firstWeekday, targetChart, title);
}
private class RefreshTask extends CancelableTask
public static class RefreshTask extends CancelableTask
{
double todayValue;
double thisWeekValue;
@ -97,11 +99,30 @@ public class TargetCard extends HabitCard
double thisQuarterValue;
double thisYearValue;
private Context context;
private Habit habit;
private int firstWeekday;
private TargetChart chart;
private TextView title;
public RefreshTask(@NonNull Context context,
@NonNull Habit habit,
int firstWeekday,
@NonNull TargetChart chart,
@Nullable TextView title)
{
this.context = context;
this.habit = habit;
this.firstWeekday = firstWeekday;
this.chart = chart;
this.title = title;
}
@Override
public void doInBackground()
{
if (isCanceled()) return;
CheckmarkList checkmarks = getHabit().getCheckmarks();
CheckmarkList checkmarks = habit.getCheckmarks();
todayValue = checkmarks.getTodayValue() / 1e3;
thisWeekValue = checkmarks.getThisWeekValue(firstWeekday) / 1e3;
thisMonthValue = checkmarks.getThisMonthValue() / 1e3;
@ -113,15 +134,14 @@ public class TargetCard extends HabitCard
public void onPostExecute()
{
if (isCanceled()) return;
Calendar cal = DateUtils.getStartOfTodayCalendar();
int daysInMonth = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
int daysInQuarter = 91;
int daysInYear = cal.getActualMaximum(Calendar.DAY_OF_YEAR);
int den = getHabit().getFrequency().getDenominator();
double dailyTarget = getHabit().getTargetValue() / den;
Resources res = getResources();
int den = habit.getFrequency().getDenominator();
double dailyTarget = habit.getTargetValue() / den;
Resources res = context.getResources();
ArrayList<Double> values = new ArrayList<>();
if (den <= 1) values.add(todayValue);
@ -129,7 +149,7 @@ public class TargetCard extends HabitCard
values.add(thisMonthValue);
values.add(thisQuarterValue);
values.add(thisYearValue);
targetChart.setValues(values);
chart.setValues(values);
ArrayList<Double> targets = new ArrayList<>();
if (den <= 1) targets.add(dailyTarget);
@ -137,7 +157,7 @@ public class TargetCard extends HabitCard
targets.add(dailyTarget * daysInMonth);
targets.add(dailyTarget * daysInQuarter);
targets.add(dailyTarget * daysInYear);
targetChart.setTargets(targets);
chart.setTargets(targets);
ArrayList<String> labels = new ArrayList<>();
if (den <= 1) labels.add(res.getString(R.string.today));
@ -145,15 +165,15 @@ public class TargetCard extends HabitCard
labels.add(res.getString(R.string.month));
labels.add(res.getString(R.string.quarter));
labels.add(res.getString(R.string.year));
targetChart.setLabels(labels);
chart.setLabels(labels);
}
@Override
public void onPreExecute()
{
int color = PaletteUtils.getColor(getContext(), getHabit().getColor());
title.setTextColor(color);
targetChart.setColor(color);
int color = PaletteUtils.getColor(context, habit.getColor());
if(title != null) title.setTextColor(color);
chart.setColor(color);
}
}
}

@ -12,7 +12,8 @@ public enum StackWidgetType {
FREQUENCY(1),
SCORE(2), // habit strength widget
HISTORY(3),
STREAKS(4);
STREAKS(4),
TARGET(5);
private int value;
StackWidgetType(int value) {
@ -34,6 +35,8 @@ public enum StackWidgetType {
return HISTORY;
} else if (STREAKS.getValue() == value) {
return STREAKS;
} else if (TARGET.getValue() == value) {
return TARGET;
}
return null;
}
@ -50,6 +53,8 @@ public enum StackWidgetType {
return R.layout.history_stackview_widget;
case STREAKS:
return R.layout.streak_stackview_widget;
case TARGET:
return R.layout.target_stackview_widget;
}
return 0;
}
@ -66,6 +71,8 @@ public enum StackWidgetType {
return R.id.historyStackWidgetView;
case STREAKS:
return R.id.streakStackWidgetView;
case TARGET:
return R.id.targetStackWidgetView;
}
return 0;
}
@ -82,6 +89,8 @@ public enum StackWidgetType {
return R.id.historyStackWidgetEmptyView;
case STREAKS:
return R.id.streakStackWidgetEmptyView;
case TARGET:
return R.id.targetStackWidgetEmptyView;
}
return 0;
}

@ -0,0 +1,60 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.widgets
import android.content.*
import android.view.*
import android.view.ViewGroup.*
import android.view.ViewGroup.LayoutParams.*
import org.isoron.uhabits.activities.common.views.*
import org.isoron.uhabits.activities.habits.show.views.*
import org.isoron.uhabits.core.models.*
import org.isoron.uhabits.widgets.views.*
class TargetWidget(
context: Context,
id: Int,
private val habit: Habit
) : BaseWidget(context, id) {
override fun getOnClickPendingIntent(context: Context) =
pendingIntentFactory.showHabit(habit)
override fun refreshData(view: View) {
val widgetView = view as GraphWidgetView
widgetView.setBackgroundAlpha(preferedBackgroundAlpha)
val chart = (widgetView.dataView as TargetChart)
with(TargetCard.RefreshTask(context, habit, prefs.firstWeekday, chart, null)) {
onPreExecute()
doInBackground()
onPostExecute()
}
}
override fun buildView(): View {
return GraphWidgetView(context, TargetChart(context)).apply {
setTitle(habit.name)
layoutParams = LayoutParams(MATCH_PARENT, MATCH_PARENT)
}
}
override fun getDefaultHeight() = 200
override fun getDefaultWidth() = 200
}

@ -0,0 +1,29 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.widgets
import android.content.*
class TargetWidgetProvider : BaseWidgetProvider() {
override fun getWidgetFromId(context: Context, id: Int): BaseWidget {
val habits = getHabitsFromWidgetId(id)
if (habits.size == 1) return TargetWidget(context, id, habits[0])
else return StackWidget(context, id, StackWidgetType.TARGET, habits)
}
}

@ -67,6 +67,7 @@ class WidgetUpdater
updateWidgets(modifiedHabitId, ScoreWidgetProvider::class.java)
updateWidgets(modifiedHabitId, StreakWidgetProvider::class.java)
updateWidgets(modifiedHabitId, FrequencyWidgetProvider::class.java)
updateWidgets(modifiedHabitId, TargetWidgetProvider::class.java)
}
}

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<StackView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/targetStackWidgetView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:loopViews="true" />
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/targetStackWidgetEmptyView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/streaks_stack_widget"
android:gravity="center"
android:textColor="#ffffff"
android:textStyle="bold"
android:textSize="16sp" />
</FrameLayout>
Loading…
Cancel
Save