Allow multiple-habits on strength chart

Now when creating a widget from several habits, if you choose "Habit
strength" as the type, then instead of stacking, they will be displayed
on the same chart.
pull/446/head
John Knox 7 years ago
parent 6a3e430a5e
commit 5d331250e4

@ -21,7 +21,6 @@ package org.isoron.uhabits.activities.common.views;
import android.content.*;
import android.graphics.*;
import android.support.annotation.*;
import android.util.*;
import org.isoron.androidbase.utils.*;
@ -71,10 +70,7 @@ public class ScoreChart extends ScrollableChart
private int gridColor;
@Nullable
private List<Score> scores;
private int primaryColor;
private List<Habit> habits = new ArrayList<>();
@Deprecated
private int bucketSize = 7;
@ -93,6 +89,8 @@ public class ScoreChart extends ScrollableChart
private String previousMonthText;
private boolean drawFooter;
public ScoreChart(Context context)
{
super(context);
@ -108,7 +106,6 @@ public class ScoreChart extends ScrollableChart
public void populateWithRandomData()
{
Random random = new Random();
scores = new LinkedList<>();
double previous = 0.5f;
Timestamp timestamp = DateUtils.getToday();
@ -118,7 +115,6 @@ public class ScoreChart extends ScrollableChart
double step = 0.1f;
double current = previous + random.nextDouble() * step * 2 - step;
current = Math.max(0, Math.min(1.0f, current));
scores.add(new Score(timestamp.minus(i), current));
previous = current;
}
}
@ -130,21 +126,15 @@ public class ScoreChart extends ScrollableChart
postInvalidate();
}
public void setIsTransparencyEnabled(boolean enabled)
{
this.isTransparencyEnabled = enabled;
public void setHabits(List<Habit> habits) {
this.habits = habits;
postInvalidate();
}
public void setColor(int primaryColor)
{
this.primaryColor = primaryColor;
postInvalidate();
}
public void setScores(@NonNull List<Score> scores)
public void setIsTransparencyEnabled(boolean enabled)
{
this.scores = scores;
this.isTransparencyEnabled = enabled;
postInvalidate();
}
@ -166,7 +156,7 @@ public class ScoreChart extends ScrollableChart
activeCanvas = canvas;
}
if (scores == null) return;
if (habits.isEmpty()) return;
rect.set(0, 0, nColumns * columnWidth, columnHeight);
rect.offset(0, paddingTop);
@ -174,7 +164,18 @@ public class ScoreChart extends ScrollableChart
drawGrid(activeCanvas, rect);
pText.setColor(textColor);
pGraph.setColor(primaryColor);
prevRect.setEmpty();
previousMonthText = "";
previousYearText = "";
skipYear = 0;
drawFooter = true;
for (Habit habit: habits)
{
pText.setColor(textColor);
pGraph.setColor(color(habit.getColor()));
prevRect.setEmpty();
previousMonthText = "";
@ -183,6 +184,7 @@ public class ScoreChart extends ScrollableChart
for (int k = 0; k < nColumns; k++)
{
List<Score> scores = habit.getScores().toList();
int offset = nColumns - k - 1 + getDataOffset();
if (offset >= scores.size()) continue;
@ -197,18 +199,23 @@ public class ScoreChart extends ScrollableChart
if (!prevRect.isEmpty())
{
drawLine(activeCanvas, prevRect, rect);
drawMarker(activeCanvas, prevRect);
drawLine(activeCanvas, prevRect, rect, habit.getColor());
drawMarker(activeCanvas, prevRect, habit.getColor());
}
if (k == nColumns - 1) drawMarker(activeCanvas, rect);
if (k == nColumns - 1) drawMarker(activeCanvas, rect, habit.getColor());
prevRect.set(rect);
rect.set(0, 0, columnWidth, columnHeight);
rect.offset(k * columnWidth, paddingTop);
drawFooter(activeCanvas, rect, timestamp);
if (drawFooter) drawFooter(activeCanvas, rect, timestamp);
}
prevRect.setEmpty();
drawFooter = false;
}
if (activeCanvas != canvas) canvas.drawBitmap(drawingCache, 0, 0, null);
}
@ -328,21 +335,21 @@ public class ScoreChart extends ScrollableChart
canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top, pGrid);
}
private void drawLine(Canvas canvas, RectF rectFrom, RectF rectTo)
private void drawLine(Canvas canvas, RectF rectFrom, RectF rectTo, int colorIndex)
{
pGraph.setColor(primaryColor);
pGraph.setColor(color(colorIndex));
canvas.drawLine(rectFrom.centerX(), rectFrom.centerY(),
rectTo.centerX(), rectTo.centerY(), pGraph);
}
private void drawMarker(Canvas canvas, RectF rect)
private void drawMarker(Canvas canvas, RectF rect, int colorIndex)
{
rect.inset(baseSize * 0.225f, baseSize * 0.225f);
setModeOrColor(pGraph, XFERMODE_CLEAR, backgroundColor);
canvas.drawOval(rect, pGraph);
rect.inset(baseSize * 0.1f, baseSize * 0.1f);
setModeOrColor(pGraph, XFERMODE_SRC, primaryColor);
setModeOrColor(pGraph, XFERMODE_SRC, color(colorIndex));
canvas.drawOval(rect, pGraph);
// rect.inset(baseSize * 0.1f, baseSize * 0.1f);
@ -352,6 +359,10 @@ public class ScoreChart extends ScrollableChart
if (isTransparencyEnabled) pGraph.setXfermode(XFERMODE_SRC);
}
private int color(int colorIndex) {
return PaletteUtils.getColor(getContext(), colorIndex);
}
private float getMaxDayWidth()
{
float maxDayWidth = 0;
@ -402,7 +413,6 @@ public class ScoreChart extends ScrollableChart
{
StyledResources res = new StyledResources(getContext());
primaryColor = Color.BLACK;
textColor = res.getColor(R.attr.mediumContrastTextColor);
gridColor = res.getColor(R.attr.lowContrastTextColor);
backgroundColor = res.getColor(R.attr.cardBackgroundColor);

@ -128,7 +128,6 @@ public class ScoreCard extends HabitCard
{
spinner.setVisibility(GONE);
title.setTextColor(PaletteUtils.getAndroidTestColor(1));
chart.setColor(PaletteUtils.getAndroidTestColor(1));
chart.populateWithRandomData();
}
}
@ -151,7 +150,9 @@ public class ScoreCard extends HabitCard
if (bucketSize == 1) scores = scoreList.toList();
else scores = scoreList.groupBy(getTruncateField(bucketSize));
chart.setScores(scores);
List<Habit> habits = new ArrayList<>();
habits.add(getHabit());
chart.setHabits(habits);
chart.setBucketSize(bucketSize);
}
@ -161,7 +162,6 @@ public class ScoreCard extends HabitCard
int color =
PaletteUtils.getColor(getContext(), getHabit().getColor());
title.setTextColor(color);
chart.setColor(color);
}
}
}

@ -37,7 +37,7 @@ class FrequencyWidget(
override fun refreshData(v: View) {
val widgetView = v as GraphWidgetView
widgetView.setTitle(habit.name)
widgetView.setHabits(listOf(habit))
(widgetView.dataView as FrequencyChart).apply {
setColor(PaletteUtils.getColor(context, habit.color))
setFrequency(habit.repetitions.weekdayFrequency)

@ -47,7 +47,7 @@ class HistoryWidget(
override fun buildView() =
GraphWidgetView(context, HistoryChart(context)).apply {
setTitle(habit.name)
setHabits(listOf(habit))
}
override fun getDefaultHeight() = 250

@ -24,37 +24,31 @@ import android.view.*
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.utils.*
import org.isoron.uhabits.widgets.views.*
class ScoreWidget(
context: Context,
id: Int,
private val habit: Habit
private val habits: List<Habit>
) : BaseWidget(context, id) {
override fun getOnClickPendingIntent(context: Context) =
pendingIntentFactory.showHabit(habit)
pendingIntentFactory.showHabit(habits.get(0))
override fun refreshData(view: View) {
val size = ScoreCard.BUCKET_SIZES[prefs.defaultScoreSpinnerPosition]
val scores = when(size) {
1 -> habit.scores.toList()
else -> habit.scores.groupBy(ScoreCard.getTruncateField(size))
}
val widgetView = view as GraphWidgetView
(widgetView.dataView as ScoreChart).apply {
setIsTransparencyEnabled(true)
setBucketSize(size)
setColor(PaletteUtils.getColor(context, habit.color))
setScores(scores)
setHabits(habits)
}
}
override fun buildView() =
GraphWidgetView(context, ScoreChart(context)).apply {
setTitle(habit.name)
setHabits(habits)
}
override fun getDefaultHeight() = 300

@ -23,7 +23,6 @@ import android.content.*
class ScoreWidgetProvider : BaseWidgetProvider() {
override fun getWidgetFromId(context: Context, id: Int): BaseWidget {
val habits = getHabitsFromWidgetId(id)
if (habits.size == 1) return ScoreWidget(context, id, habits[0])
else return StackWidget(context, id, StackWidgetType.SCORE, habits)
return ScoreWidget(context, id, habits)
}
}

@ -95,8 +95,11 @@ class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory
return new CheckmarkWidget(context, widgetId, habit);
case FREQUENCY:
return new FrequencyWidget(context, widgetId, habit);
case SCORE:
return new ScoreWidget(context, widgetId, habit);
case SCORE:{
List<Habit> list = new ArrayList<>();
list.add(habit);
return new ScoreWidget(context, widgetId, list);
}
case HISTORY:
return new HistoryWidget(context, widgetId, habit);
case STREAKS:

@ -47,7 +47,7 @@ class StreakWidget(
override fun buildView(): View {
return GraphWidgetView(context, StreakChart(context)).apply {
setTitle(habit.name)
setHabits(listOf(habit))
layoutParams = LayoutParams(MATCH_PARENT, MATCH_PARENT)
}
}

@ -20,18 +20,25 @@
package org.isoron.uhabits.widgets.views;
import android.content.*;
import android.graphics.Color;
import android.support.annotation.*;
import android.view.*;
import android.widget.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.core.models.Habit;
import org.isoron.uhabits.utils.PaletteUtils;
import java.util.List;
public class GraphWidgetView extends HabitWidgetView
{
private final View dataView;
private TextView title;
private LinearLayout legend;
private List<Habit> habits;
public GraphWidgetView(Context context, View dataView)
{
@ -45,9 +52,18 @@ public class GraphWidgetView extends HabitWidgetView
return dataView;
}
public void setTitle(String text)
{
title.setText(text);
public void setHabits(List<Habit> habits) {
for (Habit habit : habits) {
TextView t = new TextView(getContext());
if (habits.size() == 1) {
t.setTextColor(Color.WHITE);
} else {
t.setTextColor(PaletteUtils.getColor(getContext(), habit.getColor()));
}
t.setPadding(7, 0, 7, 0);
t.setText(habit.getName());
legend.addView(t);
}
}
@Override
@ -67,7 +83,6 @@ public class GraphWidgetView extends HabitWidgetView
ViewGroup innerFrame = (ViewGroup) findViewById(R.id.innerFrame);
innerFrame.addView(dataView);
title = (TextView) findViewById(R.id.title);
title.setVisibility(VISIBLE);
legend = (LinearLayout) findViewById(R.id.legend);
}
}

@ -38,12 +38,12 @@
android:paddingBottom="4dp"
tools:ignore="UselessParent">
<TextView
android:id="@+id/title"
<LinearLayout
android:id="@+id/legend"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@color/white"/>
android:orientation="horizontal"/>
</LinearLayout>

Loading…
Cancel
Save