diff --git a/app/src/main/java/org/isoron/uhabits/ui/BaseSystem.java b/app/src/main/java/org/isoron/uhabits/ui/BaseSystem.java
index a95f90f0..e1c7e106 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/BaseSystem.java
+++ b/app/src/main/java/org/isoron/uhabits/ui/BaseSystem.java
@@ -161,7 +161,7 @@ public class BaseSystem
Environment.getExternalStorageState());
}
- private String getLogcat() throws IOException
+ public String getLogcat() throws IOException
{
int maxLineCount = 250;
StringBuilder builder = new StringBuilder();
diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/controllers/HabitCardListController.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/controllers/HabitCardListController.java
index 2cfb03c9..ebb69d60 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/controllers/HabitCardListController.java
+++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/controllers/HabitCardListController.java
@@ -306,7 +306,7 @@ public class HabitCardListController implements DragSortListView.DropListener,
protected void notifyListener()
{
- if (habitListener == null) return;
+ if(selectionListener == null) return;
if (activeMode == SELECTION_MODE)
selectionListener.onSelectionChange();
diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/CheckmarkButtonView.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/CheckmarkButtonView.java
index 2fcd3440..ef6f7f2c 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/CheckmarkButtonView.java
+++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/CheckmarkButtonView.java
@@ -68,8 +68,8 @@ public class CheckmarkButtonView extends FrameLayout
public void toggle()
{
- value = (value == Checkmark.CHECKED_EXPLICITLY ? Checkmark.UNCHECKED :
- Checkmark.CHECKED_EXPLICITLY);
+// value = (value == Checkmark.CHECKED_EXPLICITLY ? Checkmark.UNCHECKED :
+// Checkmark.CHECKED_EXPLICITLY);
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
postInvalidate();
diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/HabitCardListView.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/HabitCardListView.java
index e1d0832a..52366774 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/HabitCardListView.java
+++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/HabitCardListView.java
@@ -111,13 +111,6 @@ public class HabitCardListView extends DragSortListView
});
}
- public void toggleShowArchived()
- {
-// showArchived = !showArchived;
-// cache.setIncludeArchived(showArchived);
-// cache.refreshAllHabits(true);
- }
-
@Override
protected void onAttachedToWindow()
{
diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitActivity.java b/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitActivity.java
index 4825f1fa..bbd7fa62 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitActivity.java
+++ b/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitActivity.java
@@ -33,7 +33,7 @@ import javax.inject.*;
/**
* Activity that allows the user to see more information about a single habit.
- *
+ *
* Shows all the metadata for the habit, in addition to several charts.
*/
public class ShowHabitActivity extends BaseActivity
@@ -43,19 +43,9 @@ public class ShowHabitActivity extends BaseActivity
@Inject
HabitList habitList;
- @Override
- protected void onCreate(Bundle savedInstanceState)
+ public Habit getHabit()
{
- super.onCreate(savedInstanceState);
- HabitsApplication.getComponent().inject(this);
-
- Uri data = getIntent().getData();
- habit = habitList.getById(ContentUris.parseId(data));
-
- setContentView(R.layout.show_habit_activity);
- BaseScreen.setupActionBarColor(this, ColorUtils.getColor(this, habit.getColor()));
-
- setupHabitActionBar();
+ return habit;
}
public void setupHabitActionBar()
@@ -68,8 +58,19 @@ public class ShowHabitActivity extends BaseActivity
actionBar.setTitle(habit.getName());
}
- public Habit getHabit()
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
{
- return habit;
+ super.onCreate(savedInstanceState);
+ HabitsApplication.getComponent().inject(this);
+
+ Uri data = getIntent().getData();
+ habit = habitList.getById(ContentUris.parseId(data));
+
+ setContentView(R.layout.show_habit_activity);
+ BaseScreen.setupActionBarColor(this,
+ ColorUtils.getColor(this, habit.getColor()));
+
+ setupHabitActionBar();
}
}
diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitFragment.java b/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitFragment.java
index ac2c611f..56279b76 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitFragment.java
+++ b/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitFragment.java
@@ -195,16 +195,11 @@ public class ShowHabitFragment extends Fragment
public void onModelChange()
{
refreshData();
- activity.runOnUiThread(new Runnable()
- {
- @Override
- public void run()
- {
- helper.updateColors();
- helper.updateMainHeader(getView());
- helper.updateCardHeaders(getView());
- if (activity != null) activity.setupHabitActionBar();
- }
+ activity.runOnUiThread(() -> {
+ helper.updateColors();
+ helper.updateMainHeader(getView());
+ helper.updateCardHeaders(getView());
+ if (activity != null) activity.setupHabitActionBar();
});
}
diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitHelper.java b/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitHelper.java
index dabc9a3c..d0a34000 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitHelper.java
+++ b/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitHelper.java
@@ -19,16 +19,14 @@
package org.isoron.uhabits.ui.habits.show;
-import android.content.res.Resources;
-import android.view.View;
-import android.widget.TextView;
+import android.content.res.*;
+import android.view.*;
+import android.widget.*;
-import org.isoron.uhabits.R;
-import org.isoron.uhabits.models.Score;
-import org.isoron.uhabits.ui.habits.show.views.RingView;
-import org.isoron.uhabits.utils.ColorUtils;
-import org.isoron.uhabits.utils.DateUtils;
-import org.isoron.uhabits.utils.InterfaceUtils;
+import org.isoron.uhabits.*;
+import org.isoron.uhabits.models.*;
+import org.isoron.uhabits.ui.habits.show.views.*;
+import org.isoron.uhabits.utils.*;
public class ShowHabitHelper
{
@@ -63,44 +61,33 @@ public class ShowHabitHelper
resources.getString(R.string.days));
}
- void updateScore(View view)
+ void updateCardHeaders(View view)
{
- if (fragment.habit == null) return;
- if (view == null) return;
+ updateColor(view, R.id.tvHistory);
+ updateColor(view, R.id.tvOverview);
+ updateColor(view, R.id.tvStrength);
+ updateColor(view, R.id.tvStreaks);
+ updateColor(view, R.id.tvWeekdayFreq);
+ updateColor(view, R.id.scoreLabel);
+ }
- float todayPercentage = fragment.todayScore / Score.MAX_VALUE;
- float monthDiff =
- todayPercentage - (fragment.lastMonthScore / Score.MAX_VALUE);
- float yearDiff =
- todayPercentage - (fragment.lastYearScore / Score.MAX_VALUE);
+ void updateColor(View view, int viewId)
+ {
+ if (fragment.habit == null || fragment.activity == null) return;
- RingView scoreRing = (RingView) view.findViewById(R.id.scoreRing);
+ TextView textView = (TextView) view.findViewById(viewId);
int androidColor =
- ColorUtils.getColor(fragment.getActivity(),
- fragment.habit.getColor());
- scoreRing.setColor(androidColor);
- scoreRing.setPercentage(todayPercentage);
+ ColorUtils.getColor(fragment.activity, fragment.habit.getColor());
+ textView.setTextColor(androidColor);
+ }
- TextView scoreLabel = (TextView) view.findViewById(R.id.scoreLabel);
- TextView monthDiffLabel =
- (TextView) view.findViewById(R.id.monthDiffLabel);
- TextView yearDiffLabel =
- (TextView) view.findViewById(R.id.yearDiffLabel);
-
- scoreLabel.setText(String.format("%.0f%%", todayPercentage * 100));
-
- String minus = "\u2212";
- monthDiffLabel.setText(
- String.format("%s%.0f%%", (monthDiff >= 0 ? "+" : minus),
- Math.abs(monthDiff) * 100));
- yearDiffLabel.setText(
- String.format("%s%.0f%%", (yearDiff >= 0 ? "+" : minus),
- Math.abs(yearDiff) * 100));
-
- monthDiffLabel.setTextColor(
- monthDiff >= 0 ? fragment.activeColor : fragment.inactiveColor);
- yearDiffLabel.setTextColor(
- yearDiff >= 0 ? fragment.activeColor : fragment.inactiveColor);
+ void updateColors()
+ {
+ fragment.activeColor = ColorUtils.getColor(fragment.getContext(),
+ fragment.habit.getColor());
+ fragment.inactiveColor =
+ InterfaceUtils.getStyledColor(fragment.getContext(),
+ R.attr.mediumContrastTextColor);
}
void updateMainHeader(View view)
@@ -129,33 +116,42 @@ public class ShowHabitHelper
questionLabel.setVisibility(View.GONE);
}
- void updateCardHeaders(View view)
+ void updateScore(View view)
{
- updateColor(view, R.id.tvHistory);
- updateColor(view, R.id.tvOverview);
- updateColor(view, R.id.tvStrength);
- updateColor(view, R.id.tvStreaks);
- updateColor(view, R.id.tvWeekdayFreq);
- updateColor(view, R.id.scoreLabel);
- }
+ if (fragment.habit == null) return;
+ if (view == null) return;
- void updateColor(View view, int viewId)
- {
- if (fragment.habit == null || fragment.activity == null) return;
+ float todayPercentage = fragment.todayScore / Score.MAX_VALUE;
+ float monthDiff =
+ todayPercentage - (fragment.lastMonthScore / Score.MAX_VALUE);
+ float yearDiff =
+ todayPercentage - (fragment.lastYearScore / Score.MAX_VALUE);
- TextView textView = (TextView) view.findViewById(viewId);
- int androidColor =
- ColorUtils.getColor(fragment.activity, fragment.habit.getColor());
- textView.setTextColor(androidColor);
- }
+ RingView scoreRing = (RingView) view.findViewById(R.id.scoreRing);
+ int androidColor = ColorUtils.getColor(fragment.getActivity(),
+ fragment.habit.getColor());
+ scoreRing.setColor(androidColor);
+ scoreRing.setPercentage(todayPercentage);
- void updateColors()
- {
- fragment.activeColor =
- ColorUtils.getColor(fragment.getContext(),
- fragment.habit.getColor());
- fragment.inactiveColor =
- InterfaceUtils.getStyledColor(fragment.getContext(),
- R.attr.mediumContrastTextColor);
+ TextView scoreLabel = (TextView) view.findViewById(R.id.scoreLabel);
+ TextView monthDiffLabel =
+ (TextView) view.findViewById(R.id.monthDiffLabel);
+ TextView yearDiffLabel =
+ (TextView) view.findViewById(R.id.yearDiffLabel);
+
+ scoreLabel.setText(String.format("%.0f%%", todayPercentage * 100));
+
+ String minus = "\u2212";
+ monthDiffLabel.setText(
+ String.format("%s%.0f%%", (monthDiff >= 0 ? "+" : minus),
+ Math.abs(monthDiff) * 100));
+ yearDiffLabel.setText(
+ String.format("%s%.0f%%", (yearDiff >= 0 ? "+" : minus),
+ Math.abs(yearDiff) * 100));
+
+ monthDiffLabel.setTextColor(
+ monthDiff >= 0 ? fragment.activeColor : fragment.inactiveColor);
+ yearDiffLabel.setTextColor(
+ yearDiff >= 0 ? fragment.activeColor : fragment.inactiveColor);
}
}
diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitFrequencyView.java b/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitFrequencyView.java
index dd8fbdb2..f2431752 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitFrequencyView.java
+++ b/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitFrequencyView.java
@@ -19,48 +19,53 @@
package org.isoron.uhabits.ui.habits.show.views;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.RectF;
-import android.util.AttributeSet;
+import android.content.*;
+import android.graphics.*;
+import android.util.*;
-import org.isoron.uhabits.R;
-import org.isoron.uhabits.models.Habit;
-import org.isoron.uhabits.models.ModelObservable;
-import org.isoron.uhabits.tasks.BaseTask;
-import org.isoron.uhabits.utils.ColorUtils;
-import org.isoron.uhabits.utils.DateUtils;
-import org.isoron.uhabits.utils.InterfaceUtils;
+import org.isoron.uhabits.*;
+import org.isoron.uhabits.models.*;
+import org.isoron.uhabits.tasks.*;
+import org.isoron.uhabits.utils.*;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.HashMap;
-import java.util.Random;
+import java.text.*;
+import java.util.*;
-public class HabitFrequencyView extends ScrollableDataView implements HabitDataView, ModelObservable.Listener
+public class HabitFrequencyView extends ScrollableDataView
+ implements HabitDataView, ModelObservable.Listener
{
private Paint pGrid;
+
private float em;
+
private Habit habit;
+
private SimpleDateFormat dfMonth;
+
private SimpleDateFormat dfYear;
private Paint pText, pGraph;
+
private RectF rect, prevRect;
+
private int baseSize;
+
private int paddingTop;
private float columnWidth;
+
private int columnHeight;
+
private int nColumns;
private int textColor;
+
private int gridColor;
+
private int[] colors;
+
private int primaryColor;
+
private boolean isBackgroundTransparent;
private HashMap frequency;
@@ -79,40 +84,34 @@ public class HabitFrequencyView extends ScrollableDataView implements HabitDataV
init();
}
+ @Override
+ public void onModelChange()
+ {
+ refreshData();
+ }
+
+ public void refreshData()
+ {
+ if (isInEditMode()) generateRandomData();
+ else if (habit != null)
+ {
+ frequency = habit.getRepetitions().getWeekdayFrequency();
+ createColors();
+ }
+
+ postInvalidate();
+ }
+
public void setHabit(Habit habit)
{
this.habit = habit;
createColors();
}
- private void init()
+ public void setIsBackgroundTransparent(boolean isBackgroundTransparent)
{
- createPaints();
+ this.isBackgroundTransparent = isBackgroundTransparent;
createColors();
-
- dfMonth = DateUtils.getDateFormat("MMM");
- dfYear = DateUtils.getDateFormat("yyyy");
-
- rect = new RectF();
- prevRect = new RectF();
- }
-
- private void createColors()
- {
- if(habit != null)
- {
- this.primaryColor = ColorUtils.getColor(getContext(),
- habit.getColor());
- }
-
- textColor = InterfaceUtils.getStyledColor(getContext(), R.attr.mediumContrastTextColor);
- gridColor = InterfaceUtils.getStyledColor(getContext(), R.attr.lowContrastTextColor);
-
- colors = new int[4];
- colors[0] = gridColor;
- colors[3] = primaryColor;
- colors[1] = ColorUtils.mixColors(colors[0], colors[3], 0.66f);
- colors[2] = ColorUtils.mixColors(colors[0], colors[3], 0.33f);
}
protected void createPaints()
@@ -128,181 +127,6 @@ public class HabitFrequencyView extends ScrollableDataView implements HabitDataV
pGrid.setAntiAlias(true);
}
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
- {
- int width = MeasureSpec.getSize(widthMeasureSpec);
- int height = MeasureSpec.getSize(heightMeasureSpec);
- setMeasuredDimension(width, height);
- }
-
- @Override
- protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
- {
- if(height < 9) height = 200;
-
- baseSize = height / 8;
- setScrollerBucketSize(baseSize);
-
- pText.setTextSize(baseSize * 0.4f);
- pGraph.setTextSize(baseSize * 0.4f);
- pGraph.setStrokeWidth(baseSize * 0.1f);
- pGrid.setStrokeWidth(baseSize * 0.05f);
- em = pText.getFontSpacing();
-
- columnWidth = baseSize;
- columnWidth = Math.max(columnWidth, getMaxMonthWidth() * 1.2f);
-
- columnHeight = 8 * baseSize;
- nColumns = (int) (width / columnWidth);
- paddingTop = 0;
- }
-
- private float getMaxMonthWidth()
- {
- float maxMonthWidth = 0;
- GregorianCalendar day = DateUtils.getStartOfTodayCalendar();
-
- for(int i = 0; i < 12; i++)
- {
- day.set(Calendar.MONTH, i);
- float monthWidth = pText.measureText(dfMonth.format(day.getTime()));
- maxMonthWidth = Math.max(maxMonthWidth, monthWidth);
- }
-
- return maxMonthWidth;
- }
-
- public void refreshData()
- {
- if(isInEditMode()) generateRandomData();
- else if(habit != null)
- {
- frequency = habit.getRepetitions().getWeekdayFrequency();
- createColors();
- }
-
- postInvalidate();
- }
-
- private void generateRandomData()
- {
- GregorianCalendar date = DateUtils.getStartOfTodayCalendar();
- date.set(Calendar.DAY_OF_MONTH, 1);
- Random rand = new Random();
- frequency.clear();
-
- for(int i = 0; i < 40; i++)
- {
- Integer values[] = new Integer[7];
- for(int j = 0; j < 7; j++)
- values[j] = rand.nextInt(5);
-
- frequency.put(date.getTimeInMillis(), values);
- date.add(Calendar.MONTH, -1);
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas)
- {
- super.onDraw(canvas);
-
- rect.set(0, 0, nColumns * columnWidth, columnHeight);
- rect.offset(0, paddingTop);
-
- drawGrid(canvas, rect);
-
- pText.setTextAlign(Paint.Align.CENTER);
- pText.setColor(textColor);
- pGraph.setColor(primaryColor);
- prevRect.setEmpty();
-
- GregorianCalendar currentDate = DateUtils.getStartOfTodayCalendar();
-
- currentDate.set(Calendar.DAY_OF_MONTH, 1);
- currentDate.add(Calendar.MONTH, -nColumns + 2 - getDataOffset());
-
- for(int i = 0; i < nColumns - 1; i++)
- {
- rect.set(0, 0, columnWidth, columnHeight);
- rect.offset(i * columnWidth, 0);
-
- drawColumn(canvas, rect, currentDate);
- currentDate.add(Calendar.MONTH, 1);
- }
- }
-
- private void drawColumn(Canvas canvas, RectF rect, GregorianCalendar date)
- {
- Integer values[] = frequency.get(date.getTimeInMillis());
- float rowHeight = rect.height() / 8.0f;
- prevRect.set(rect);
-
- Integer[] localeWeekdayList = DateUtils.getLocaleWeekdayList();
- for (int j = 0; j < localeWeekdayList.length; j++)
- {
- rect.set(0, 0, baseSize, baseSize);
- rect.offset(prevRect.left, prevRect.top + baseSize * j);
-
- int i = DateUtils.javaWeekdayToLoopWeekday(localeWeekdayList[j]);
- if(values != null)
- drawMarker(canvas, rect, values[i]);
-
- rect.offset(0, rowHeight);
- }
-
- drawFooter(canvas, rect, date);
- }
-
- private void drawFooter(Canvas canvas, RectF rect, GregorianCalendar date)
- {
- Date time = date.getTime();
-
- canvas.drawText(dfMonth.format(time), rect.centerX(), rect.centerY() - 0.1f * em, pText);
-
- if(date.get(Calendar.MONTH) == 1)
- canvas.drawText(dfYear.format(time), rect.centerX(), rect.centerY() + 0.9f * em, pText);
- }
-
- private void drawMarker(Canvas canvas, RectF rect, Integer value)
- {
- float padding = rect.height() * 0.2f;
- float radius = (rect.height() - 2 * padding) / 2.0f / 4.0f * Math.min(value, 4);
-
- pGraph.setColor(colors[Math.min(3, Math.max(0, value - 1))]);
- canvas.drawCircle(rect.centerX(), rect.centerY(), radius, pGraph);
- }
-
- private void drawGrid(Canvas canvas, RectF rGrid)
- {
- int nRows = 7;
- float rowHeight = rGrid.height() / (nRows + 1);
-
- pText.setTextAlign(Paint.Align.LEFT);
- pText.setColor(textColor);
- pGrid.setColor(gridColor);
-
- for (String day : DateUtils.getLocaleDayNames(Calendar.SHORT)) {
- canvas.drawText(day, rGrid.right - columnWidth,
- rGrid.top + rowHeight / 2 + 0.25f * em, pText);
-
- pGrid.setStrokeWidth(1f);
- canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top, pGrid);
-
- rGrid.offset(0, rowHeight);
- }
-
- canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top, pGrid);
- }
-
- public void setIsBackgroundTransparent(boolean isBackgroundTransparent)
- {
- this.isBackgroundTransparent = isBackgroundTransparent;
- createColors();
- }
-
-
@Override
protected void onAttachedToWindow()
{
@@ -328,8 +152,197 @@ public class HabitFrequencyView extends ScrollableDataView implements HabitDataV
}
@Override
- public void onModelChange()
+ protected void onDraw(Canvas canvas)
{
- refreshData();
+ super.onDraw(canvas);
+
+ rect.set(0, 0, nColumns * columnWidth, columnHeight);
+ rect.offset(0, paddingTop);
+
+ drawGrid(canvas, rect);
+
+ pText.setTextAlign(Paint.Align.CENTER);
+ pText.setColor(textColor);
+ pGraph.setColor(primaryColor);
+ prevRect.setEmpty();
+
+ GregorianCalendar currentDate = DateUtils.getStartOfTodayCalendar();
+
+ currentDate.set(Calendar.DAY_OF_MONTH, 1);
+ currentDate.add(Calendar.MONTH, -nColumns + 2 - getDataOffset());
+
+ for (int i = 0; i < nColumns - 1; i++)
+ {
+ rect.set(0, 0, columnWidth, columnHeight);
+ rect.offset(i * columnWidth, 0);
+
+ drawColumn(canvas, rect, currentDate);
+ currentDate.add(Calendar.MONTH, 1);
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
+ {
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+ setMeasuredDimension(width, height);
+ }
+
+ @Override
+ protected void onSizeChanged(int width,
+ int height,
+ int oldWidth,
+ int oldHeight)
+ {
+ if (height < 9) height = 200;
+
+ baseSize = height / 8;
+ setScrollerBucketSize(baseSize);
+
+ pText.setTextSize(baseSize * 0.4f);
+ pGraph.setTextSize(baseSize * 0.4f);
+ pGraph.setStrokeWidth(baseSize * 0.1f);
+ pGrid.setStrokeWidth(baseSize * 0.05f);
+ em = pText.getFontSpacing();
+
+ columnWidth = baseSize;
+ columnWidth = Math.max(columnWidth, getMaxMonthWidth() * 1.2f);
+
+ columnHeight = 8 * baseSize;
+ nColumns = (int) (width / columnWidth);
+ paddingTop = 0;
+ }
+
+ private void createColors()
+ {
+ if (habit != null)
+ {
+ this.primaryColor =
+ ColorUtils.getColor(getContext(), habit.getColor());
+ }
+
+ textColor = InterfaceUtils.getStyledColor(getContext(),
+ R.attr.mediumContrastTextColor);
+ gridColor = InterfaceUtils.getStyledColor(getContext(),
+ R.attr.lowContrastTextColor);
+
+ colors = new int[4];
+ colors[0] = gridColor;
+ colors[3] = primaryColor;
+ colors[1] = ColorUtils.mixColors(colors[0], colors[3], 0.66f);
+ colors[2] = ColorUtils.mixColors(colors[0], colors[3], 0.33f);
+ }
+
+ private void drawColumn(Canvas canvas, RectF rect, GregorianCalendar date)
+ {
+ Integer values[] = frequency.get(date.getTimeInMillis());
+ float rowHeight = rect.height() / 8.0f;
+ prevRect.set(rect);
+
+ Integer[] localeWeekdayList = DateUtils.getLocaleWeekdayList();
+ for (int j = 0; j < localeWeekdayList.length; j++)
+ {
+ rect.set(0, 0, baseSize, baseSize);
+ rect.offset(prevRect.left, prevRect.top + baseSize * j);
+
+ int i = DateUtils.javaWeekdayToLoopWeekday(localeWeekdayList[j]);
+ if (values != null) drawMarker(canvas, rect, values[i]);
+
+ rect.offset(0, rowHeight);
+ }
+
+ drawFooter(canvas, rect, date);
+ }
+
+ private void drawFooter(Canvas canvas, RectF rect, GregorianCalendar date)
+ {
+ Date time = date.getTime();
+
+ canvas.drawText(dfMonth.format(time), rect.centerX(),
+ rect.centerY() - 0.1f * em, pText);
+
+ if (date.get(Calendar.MONTH) == 1)
+ canvas.drawText(dfYear.format(time), rect.centerX(),
+ rect.centerY() + 0.9f * em, pText);
+ }
+
+ private void drawGrid(Canvas canvas, RectF rGrid)
+ {
+ int nRows = 7;
+ float rowHeight = rGrid.height() / (nRows + 1);
+
+ pText.setTextAlign(Paint.Align.LEFT);
+ pText.setColor(textColor);
+ pGrid.setColor(gridColor);
+
+ for (String day : DateUtils.getLocaleDayNames(Calendar.SHORT))
+ {
+ canvas.drawText(day, rGrid.right - columnWidth,
+ rGrid.top + rowHeight / 2 + 0.25f * em, pText);
+
+ pGrid.setStrokeWidth(1f);
+ canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top,
+ pGrid);
+
+ rGrid.offset(0, rowHeight);
+ }
+
+ canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top, pGrid);
+ }
+
+ private void drawMarker(Canvas canvas, RectF rect, Integer value)
+ {
+ float padding = rect.height() * 0.2f;
+ float radius =
+ (rect.height() - 2 * padding) / 2.0f / 4.0f * Math.min(value, 4);
+
+ pGraph.setColor(colors[Math.min(3, Math.max(0, value - 1))]);
+ canvas.drawCircle(rect.centerX(), rect.centerY(), radius, pGraph);
+ }
+
+ private void generateRandomData()
+ {
+ GregorianCalendar date = DateUtils.getStartOfTodayCalendar();
+ date.set(Calendar.DAY_OF_MONTH, 1);
+ Random rand = new Random();
+ frequency.clear();
+
+ for (int i = 0; i < 40; i++)
+ {
+ Integer values[] = new Integer[7];
+ for (int j = 0; j < 7; j++)
+ values[j] = rand.nextInt(5);
+
+ frequency.put(date.getTimeInMillis(), values);
+ date.add(Calendar.MONTH, -1);
+ }
+ }
+
+ private float getMaxMonthWidth()
+ {
+ float maxMonthWidth = 0;
+ GregorianCalendar day = DateUtils.getStartOfTodayCalendar();
+
+ for (int i = 0; i < 12; i++)
+ {
+ day.set(Calendar.MONTH, i);
+ float monthWidth = pText.measureText(dfMonth.format(day.getTime()));
+ maxMonthWidth = Math.max(maxMonthWidth, monthWidth);
+ }
+
+ return maxMonthWidth;
+ }
+
+ private void init()
+ {
+ createPaints();
+ createColors();
+
+ dfMonth = DateUtils.getDateFormat("MMM");
+ dfYear = DateUtils.getDateFormat("yyyy");
+
+ rect = new RectF();
+ prevRect = new RectF();
}
}
diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitHistoryView.java b/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitHistoryView.java
index b855b8e7..7f7c9a50 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitHistoryView.java
+++ b/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitHistoryView.java
@@ -19,61 +19,76 @@
package org.isoron.uhabits.ui.habits.show.views;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.RectF;
-import android.util.AttributeSet;
-import android.view.HapticFeedbackConstants;
-import android.view.MotionEvent;
+import android.content.*;
+import android.graphics.*;
+import android.graphics.Paint.*;
+import android.util.*;
+import android.view.*;
-import org.isoron.uhabits.R;
-import org.isoron.uhabits.models.Habit;
-import org.isoron.uhabits.models.ModelObservable;
-import org.isoron.uhabits.tasks.BaseTask;
-import org.isoron.uhabits.tasks.ToggleRepetitionTask;
-import org.isoron.uhabits.utils.ColorUtils;
-import org.isoron.uhabits.utils.DateUtils;
-import org.isoron.uhabits.utils.InterfaceUtils;
+import org.isoron.uhabits.*;
+import org.isoron.uhabits.models.*;
+import org.isoron.uhabits.tasks.*;
+import org.isoron.uhabits.utils.*;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.Random;
+import java.text.*;
+import java.util.*;
-public class HabitHistoryView extends ScrollableDataView implements HabitDataView,
- ToggleRepetitionTask.Listener, ModelObservable.Listener
+public class HabitHistoryView extends ScrollableDataView implements
+ HabitDataView,
+ ToggleRepetitionTask.Listener,
+ ModelObservable.Listener
{
private Habit habit;
+
private int[] checkmarks;
+
private Paint pSquareBg, pSquareFg, pTextHeader;
+
private float squareSpacing;
private float squareTextOffset;
+
private float headerTextOffset;
private float columnWidth;
+
private float columnHeight;
+
private int nColumns;
private SimpleDateFormat dfMonth;
+
private SimpleDateFormat dfYear;
private Calendar baseDate;
+
private int nDays;
- /** 0-based-position of today in the column */
+
+ /**
+ * 0-based-position of today in the column
+ */
private int todayPositionInColumn;
+
private int colors[];
+
private RectF baseLocation;
+
private int primaryColor;
private boolean isBackgroundTransparent;
+
private int textColor;
+
private int reverseTextColor;
+
private boolean isEditable;
+ private String previousMonth;
+
+ private String previousYear;
+
+ private float headerOverflow = 0;
+
public HabitHistoryView(Context context)
{
super(context);
@@ -86,273 +101,22 @@ public class HabitHistoryView extends ScrollableDataView implements HabitDataVie
init();
}
- public void setHabit(Habit habit)
- {
- this.habit = habit;
- createColors();
- }
-
- private void init()
- {
- createColors();
- createPaints();
-
- isEditable = false;
- checkmarks = new int[0];
- primaryColor = ColorUtils.getColor(getContext(), 7);
- dfMonth = DateUtils.getDateFormat("MMM");
- dfYear = DateUtils.getDateFormat("yyyy");
-
- baseLocation = new RectF();
- }
-
- private void updateDate()
- {
- baseDate = DateUtils.getStartOfTodayCalendar();
- baseDate.add(Calendar.DAY_OF_YEAR, -(getDataOffset() - 1) * 7);
-
- nDays = (nColumns - 1) * 7;
- int realWeekday = DateUtils.getStartOfTodayCalendar().get(Calendar.DAY_OF_WEEK);
- todayPositionInColumn = (7 + realWeekday - baseDate.getFirstDayOfWeek()) % 7;
-
- baseDate.add(Calendar.DAY_OF_YEAR, -nDays);
- baseDate.add(Calendar.DAY_OF_YEAR, -todayPositionInColumn);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
- {
- int width = MeasureSpec.getSize(widthMeasureSpec);
- int height = MeasureSpec.getSize(heightMeasureSpec);
- setMeasuredDimension(width, height);
- }
-
- @Override
- protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
- {
- if(height < 8) height = 200;
- float baseSize = height / 8.0f;
- setScrollerBucketSize((int) baseSize);
-
- squareSpacing = InterfaceUtils.dpToPixels(getContext(), 1.0f);
- float maxTextSize = getResources().getDimension(R.dimen.regularTextSize);
- float textSize = height * 0.06f;
- textSize = Math.min(textSize, maxTextSize);
-
- pSquareFg.setTextSize(textSize);
- pTextHeader.setTextSize(textSize);
- squareTextOffset = pSquareFg.getFontSpacing() * 0.4f;
- headerTextOffset = pTextHeader.getFontSpacing() * 0.3f;
-
- float rightLabelWidth = getWeekdayLabelWidth() + headerTextOffset;
- float horizontalPadding = getPaddingRight() + getPaddingLeft();
-
- columnWidth = baseSize;
- columnHeight = 8 * baseSize;
- nColumns = (int)((width - rightLabelWidth - horizontalPadding) / baseSize) + 1;
-
- updateDate();
- }
-
- private float getWeekdayLabelWidth()
- {
- float width = 0;
-
- for(String w : DateUtils.getLocaleDayNames(Calendar.SHORT))
- width = Math.max(width, pSquareFg.measureText(w));
-
- return width;
- }
-
- private void createColors()
- {
- if(habit != null)
- this.primaryColor = ColorUtils.getColor(getContext(),
- habit.getColor());
-
- if(isBackgroundTransparent)
- primaryColor = ColorUtils.setMinValue(primaryColor, 0.75f);
-
- int red = Color.red(primaryColor);
- int green = Color.green(primaryColor);
- int blue = Color.blue(primaryColor);
-
- if(isBackgroundTransparent)
- {
- colors = new int[3];
- colors[0] = Color.argb(16, 255, 255, 255);
- colors[1] = Color.argb(128, red, green, blue);
- colors[2] = primaryColor;
- textColor = Color.WHITE;
- reverseTextColor = Color.WHITE;
- }
- else
- {
- colors = new int[3];
- colors[0] = InterfaceUtils.getStyledColor(getContext(), R.attr.lowContrastTextColor);
- colors[1] = Color.argb(127, red, green, blue);
- colors[2] = primaryColor;
- textColor = InterfaceUtils.getStyledColor(getContext(), R.attr.mediumContrastTextColor);
- reverseTextColor = InterfaceUtils.getStyledColor(getContext(), R.attr.highContrastReverseTextColor);
- }
- }
-
- protected void createPaints()
- {
- pTextHeader = new Paint();
- pTextHeader.setTextAlign(Align.LEFT);
- pTextHeader.setAntiAlias(true);
-
- pSquareBg = new Paint();
-
- pSquareFg = new Paint();
- pSquareFg.setAntiAlias(true);
- pSquareFg.setTextAlign(Align.CENTER);
- }
-
- public void refreshData()
- {
- if(isInEditMode())
- generateRandomData();
- else
- {
- if(habit == null) return;
- checkmarks = habit.getCheckmarks().getAllValues();
- createColors();
- }
-
- updateDate();
- postInvalidate();
- }
-
- private void generateRandomData()
- {
- Random random = new Random();
- checkmarks = new int[100];
-
- for(int i = 0; i < 100; i++)
- if(random.nextFloat() < 0.3) checkmarks[i] = 2;
-
- for(int i = 0; i < 100 - 7; i++)
- {
- int count = 0;
- for (int j = 0; j < 7; j++)
- if(checkmarks[i + j] != 0)
- count++;
-
- if(count >= 3) checkmarks[i] = Math.max(checkmarks[i], 1);
- }
- }
-
- private String previousMonth;
- private String previousYear;
-
- @Override
- protected void onDraw(Canvas canvas)
- {
- super.onDraw(canvas);
-
- baseLocation.set(0, 0, columnWidth - squareSpacing, columnWidth - squareSpacing);
- baseLocation.offset(getPaddingLeft(), getPaddingTop());
-
- headerOverflow = 0;
- previousMonth = "";
- previousYear = "";
- pTextHeader.setColor(textColor);
-
- updateDate();
- GregorianCalendar currentDate = (GregorianCalendar) baseDate.clone();
-
- for (int column = 0; column < nColumns - 1; column++)
- {
- drawColumn(canvas, baseLocation, currentDate, column);
- baseLocation.offset(columnWidth, - columnHeight);
- }
-
- drawAxis(canvas, baseLocation);
- }
-
- private void drawColumn(Canvas canvas, RectF location, GregorianCalendar date, int column)
- {
- drawColumnHeader(canvas, location, date);
- location.offset(0, columnWidth);
-
- for (int j = 0; j < 7; j++)
- {
- if (!(column == nColumns - 2 && getDataOffset() == 0 && j > todayPositionInColumn))
- {
- int checkmarkOffset = getDataOffset() * 7 + nDays - 7 * (column + 1) +
- todayPositionInColumn - j;
- drawSquare(canvas, location, date, checkmarkOffset);
- }
-
- date.add(Calendar.DAY_OF_MONTH, 1);
- location.offset(0, columnWidth);
- }
- }
-
- private void drawSquare(Canvas canvas, RectF location, GregorianCalendar date,
- int checkmarkOffset)
- {
- if (checkmarkOffset >= checkmarks.length) pSquareBg.setColor(colors[0]);
- else pSquareBg.setColor(colors[checkmarks[checkmarkOffset]]);
-
- pSquareFg.setColor(reverseTextColor);
- canvas.drawRect(location, pSquareBg);
- String text = Integer.toString(date.get(Calendar.DAY_OF_MONTH));
- canvas.drawText(text, location.centerX(), location.centerY() + squareTextOffset, pSquareFg);
- }
-
- private void drawAxis(Canvas canvas, RectF location)
- {
- float verticalOffset = pTextHeader.getFontSpacing() * 0.4f;
-
- for (String day : DateUtils.getLocaleDayNames(Calendar.SHORT))
- {
- location.offset(0, columnWidth);
- canvas.drawText(day, location.left + headerTextOffset,
- location.centerY() + verticalOffset, pTextHeader);
- }
- }
-
- private float headerOverflow = 0;
-
- private void drawColumnHeader(Canvas canvas, RectF location, GregorianCalendar date)
- {
- String month = dfMonth.format(date.getTime());
- String year = dfYear.format(date.getTime());
-
- String text = null;
- if (!month.equals(previousMonth))
- text = previousMonth = month;
- else if(!year.equals(previousYear))
- text = previousYear = year;
-
- if(text != null)
- {
- canvas.drawText(text, location.left + headerOverflow, location.bottom - headerTextOffset, pTextHeader);
- headerOverflow += pTextHeader.measureText(text) + columnWidth * 0.2f;
- }
-
- headerOverflow = Math.max(0, headerOverflow - columnWidth);
- }
-
- public void setIsBackgroundTransparent(boolean isBackgroundTransparent)
- {
- this.isBackgroundTransparent = isBackgroundTransparent;
- createColors();
- }
-
@Override
public void onLongPress(MotionEvent e)
{
onSingleTapUp(e);
}
+ @Override
+ public void onModelChange()
+ {
+ refreshData();
+ }
+
@Override
public boolean onSingleTapUp(MotionEvent e)
{
- if(!isEditable) return false;
+ if (!isEditable) return false;
performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
@@ -361,7 +125,7 @@ public class HabitHistoryView extends ScrollableDataView implements HabitDataVie
float y = e.getY(pointerId);
final Long timestamp = positionToTimestamp(x, y);
- if(timestamp == null) return false;
+ if (timestamp == null) return false;
ToggleRepetitionTask task = new ToggleRepetitionTask(habit, timestamp);
task.setListener(this);
@@ -370,29 +134,6 @@ public class HabitHistoryView extends ScrollableDataView implements HabitDataVie
return true;
}
- private Long positionToTimestamp(float x, float y)
- {
- int col = (int) (x / columnWidth);
- int row = (int) (y / columnWidth);
-
- if(row == 0) return null;
- if(col == nColumns - 1) return null;
-
- int offset = col * 7 + (row - 1);
- Calendar date = (Calendar) baseDate.clone();
- date.add(Calendar.DAY_OF_YEAR, offset);
-
- if(DateUtils.getStartOfDay(date.getTimeInMillis()) > DateUtils.getStartOfToday())
- return null;
-
- return date.getTimeInMillis();
- }
-
- public void setIsEditable(boolean isEditable)
- {
- this.isEditable = isEditable;
- }
-
@Override
public void onToggleRepetitionFinished()
{
@@ -413,6 +154,51 @@ public class HabitHistoryView extends ScrollableDataView implements HabitDataVie
}.execute();
}
+ @Override
+ public void refreshData()
+ {
+ if (isInEditMode()) generateRandomData();
+ else
+ {
+ if (habit == null) return;
+ checkmarks = habit.getCheckmarks().getAllValues();
+ createColors();
+ }
+
+ updateDate();
+ postInvalidate();
+ }
+
+ public void setHabit(Habit habit)
+ {
+ this.habit = habit;
+ createColors();
+ }
+
+ public void setIsBackgroundTransparent(boolean isBackgroundTransparent)
+ {
+ this.isBackgroundTransparent = isBackgroundTransparent;
+ createColors();
+ }
+
+ public void setIsEditable(boolean isEditable)
+ {
+ this.isEditable = isEditable;
+ }
+
+ protected void createPaints()
+ {
+ pTextHeader = new Paint();
+ pTextHeader.setTextAlign(Align.LEFT);
+ pTextHeader.setAntiAlias(true);
+
+ pSquareBg = new Paint();
+
+ pSquareFg = new Paint();
+ pSquareFg.setAntiAlias(true);
+ pSquareFg.setTextAlign(Align.CENTER);
+ }
+
@Override
protected void onAttachedToWindow()
{
@@ -438,8 +224,252 @@ public class HabitHistoryView extends ScrollableDataView implements HabitDataVie
}
@Override
- public void onModelChange()
+ protected void onDraw(Canvas canvas)
{
- refreshData();
+ super.onDraw(canvas);
+
+ baseLocation.set(0, 0, columnWidth - squareSpacing,
+ columnWidth - squareSpacing);
+ baseLocation.offset(getPaddingLeft(), getPaddingTop());
+
+ headerOverflow = 0;
+ previousMonth = "";
+ previousYear = "";
+ pTextHeader.setColor(textColor);
+
+ updateDate();
+ GregorianCalendar currentDate = (GregorianCalendar) baseDate.clone();
+
+ for (int column = 0; column < nColumns - 1; column++)
+ {
+ drawColumn(canvas, baseLocation, currentDate, column);
+ baseLocation.offset(columnWidth, -columnHeight);
+ }
+
+ drawAxis(canvas, baseLocation);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
+ {
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+ setMeasuredDimension(width, height);
+ }
+
+ @Override
+ protected void onSizeChanged(int width,
+ int height,
+ int oldWidth,
+ int oldHeight)
+ {
+ if (height < 8) height = 200;
+ float baseSize = height / 8.0f;
+ setScrollerBucketSize((int) baseSize);
+
+ squareSpacing = InterfaceUtils.dpToPixels(getContext(), 1.0f);
+ float maxTextSize =
+ getResources().getDimension(R.dimen.regularTextSize);
+ float textSize = height * 0.06f;
+ textSize = Math.min(textSize, maxTextSize);
+
+ pSquareFg.setTextSize(textSize);
+ pTextHeader.setTextSize(textSize);
+ squareTextOffset = pSquareFg.getFontSpacing() * 0.4f;
+ headerTextOffset = pTextHeader.getFontSpacing() * 0.3f;
+
+ float rightLabelWidth = getWeekdayLabelWidth() + headerTextOffset;
+ float horizontalPadding = getPaddingRight() + getPaddingLeft();
+
+ columnWidth = baseSize;
+ columnHeight = 8 * baseSize;
+ nColumns =
+ (int) ((width - rightLabelWidth - horizontalPadding) / baseSize) +
+ 1;
+
+ updateDate();
+ }
+
+ private void createColors()
+ {
+ if (habit != null) this.primaryColor =
+ ColorUtils.getColor(getContext(), habit.getColor());
+
+ if (isBackgroundTransparent)
+ primaryColor = ColorUtils.setMinValue(primaryColor, 0.75f);
+
+ int red = Color.red(primaryColor);
+ int green = Color.green(primaryColor);
+ int blue = Color.blue(primaryColor);
+
+ if (isBackgroundTransparent)
+ {
+ colors = new int[3];
+ colors[0] = Color.argb(16, 255, 255, 255);
+ colors[1] = Color.argb(128, red, green, blue);
+ colors[2] = primaryColor;
+ textColor = Color.WHITE;
+ reverseTextColor = Color.WHITE;
+ }
+ else
+ {
+ colors = new int[3];
+ colors[0] = InterfaceUtils.getStyledColor(getContext(),
+ R.attr.lowContrastTextColor);
+ colors[1] = Color.argb(127, red, green, blue);
+ colors[2] = primaryColor;
+ textColor = InterfaceUtils.getStyledColor(getContext(),
+ R.attr.mediumContrastTextColor);
+ reverseTextColor = InterfaceUtils.getStyledColor(getContext(),
+ R.attr.highContrastReverseTextColor);
+ }
+ }
+
+ private void drawAxis(Canvas canvas, RectF location)
+ {
+ float verticalOffset = pTextHeader.getFontSpacing() * 0.4f;
+
+ for (String day : DateUtils.getLocaleDayNames(Calendar.SHORT))
+ {
+ location.offset(0, columnWidth);
+ canvas.drawText(day, location.left + headerTextOffset,
+ location.centerY() + verticalOffset, pTextHeader);
+ }
+ }
+
+ private void drawColumn(Canvas canvas,
+ RectF location,
+ GregorianCalendar date,
+ int column)
+ {
+ drawColumnHeader(canvas, location, date);
+ location.offset(0, columnWidth);
+
+ for (int j = 0; j < 7; j++)
+ {
+ if (!(column == nColumns - 2 && getDataOffset() == 0 &&
+ j > todayPositionInColumn))
+ {
+ int checkmarkOffset =
+ getDataOffset() * 7 + nDays - 7 * (column + 1) +
+ todayPositionInColumn - j;
+ drawSquare(canvas, location, date, checkmarkOffset);
+ }
+
+ date.add(Calendar.DAY_OF_MONTH, 1);
+ location.offset(0, columnWidth);
+ }
+ }
+
+ private void drawColumnHeader(Canvas canvas,
+ RectF location,
+ GregorianCalendar date)
+ {
+ String month = dfMonth.format(date.getTime());
+ String year = dfYear.format(date.getTime());
+
+ String text = null;
+ if (!month.equals(previousMonth)) text = previousMonth = month;
+ else if (!year.equals(previousYear)) text = previousYear = year;
+
+ if (text != null)
+ {
+ canvas.drawText(text, location.left + headerOverflow,
+ location.bottom - headerTextOffset, pTextHeader);
+ headerOverflow +=
+ pTextHeader.measureText(text) + columnWidth * 0.2f;
+ }
+
+ headerOverflow = Math.max(0, headerOverflow - columnWidth);
+ }
+
+ private void drawSquare(Canvas canvas,
+ RectF location,
+ GregorianCalendar date,
+ int checkmarkOffset)
+ {
+ if (checkmarkOffset >= checkmarks.length) pSquareBg.setColor(colors[0]);
+ else pSquareBg.setColor(colors[checkmarks[checkmarkOffset]]);
+
+ pSquareFg.setColor(reverseTextColor);
+ canvas.drawRect(location, pSquareBg);
+ String text = Integer.toString(date.get(Calendar.DAY_OF_MONTH));
+ canvas.drawText(text, location.centerX(),
+ location.centerY() + squareTextOffset, pSquareFg);
+ }
+
+ private void generateRandomData()
+ {
+ Random random = new Random();
+ checkmarks = new int[100];
+
+ for (int i = 0; i < 100; i++)
+ if (random.nextFloat() < 0.3) checkmarks[i] = 2;
+
+ for (int i = 0; i < 100 - 7; i++)
+ {
+ int count = 0;
+ for (int j = 0; j < 7; j++)
+ if (checkmarks[i + j] != 0) count++;
+
+ if (count >= 3) checkmarks[i] = Math.max(checkmarks[i], 1);
+ }
+ }
+
+ private float getWeekdayLabelWidth()
+ {
+ float width = 0;
+
+ for (String w : DateUtils.getLocaleDayNames(Calendar.SHORT))
+ width = Math.max(width, pSquareFg.measureText(w));
+
+ return width;
+ }
+
+ private void init()
+ {
+ createColors();
+ createPaints();
+
+ isEditable = false;
+ checkmarks = new int[0];
+ primaryColor = ColorUtils.getColor(getContext(), 7);
+ dfMonth = DateUtils.getDateFormat("MMM");
+ dfYear = DateUtils.getDateFormat("yyyy");
+
+ baseLocation = new RectF();
+ }
+
+ private Long positionToTimestamp(float x, float y)
+ {
+ int col = (int) (x / columnWidth);
+ int row = (int) (y / columnWidth);
+
+ if (row == 0) return null;
+ if (col == nColumns - 1) return null;
+
+ int offset = col * 7 + (row - 1);
+ Calendar date = (Calendar) baseDate.clone();
+ date.add(Calendar.DAY_OF_YEAR, offset);
+
+ if (DateUtils.getStartOfDay(date.getTimeInMillis()) >
+ DateUtils.getStartOfToday()) return null;
+
+ return date.getTimeInMillis();
+ }
+
+ private void updateDate()
+ {
+ baseDate = DateUtils.getStartOfTodayCalendar();
+ baseDate.add(Calendar.DAY_OF_YEAR, -(getDataOffset() - 1) * 7);
+
+ nDays = (nColumns - 1) * 7;
+ int realWeekday =
+ DateUtils.getStartOfTodayCalendar().get(Calendar.DAY_OF_WEEK);
+ todayPositionInColumn =
+ (7 + realWeekday - baseDate.getFirstDayOfWeek()) % 7;
+
+ baseDate.add(Calendar.DAY_OF_YEAR, -nDays);
+ baseDate.add(Calendar.DAY_OF_YEAR, -todayPositionInColumn);
}
}
diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitScoreView.java b/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitScoreView.java
index 7215430e..2d125283 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitScoreView.java
+++ b/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitScoreView.java
@@ -19,34 +19,18 @@
package org.isoron.uhabits.ui.habits.show.views;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.RectF;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.AttributeSet;
-import android.util.Log;
+import android.content.*;
+import android.graphics.*;
+import android.support.annotation.*;
+import android.util.*;
-import org.isoron.uhabits.R;
-import org.isoron.uhabits.models.Habit;
-import org.isoron.uhabits.models.ModelObservable;
-import org.isoron.uhabits.models.Score;
-import org.isoron.uhabits.tasks.BaseTask;
-import org.isoron.uhabits.utils.ColorUtils;
-import org.isoron.uhabits.utils.DateUtils;
-import org.isoron.uhabits.utils.InterfaceUtils;
+import org.isoron.uhabits.*;
+import org.isoron.uhabits.models.*;
+import org.isoron.uhabits.tasks.*;
+import org.isoron.uhabits.utils.*;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Random;
+import java.text.*;
+import java.util.*;
public class HabitScoreView extends ScrollableDataView
implements HabitDataView, ModelObservable.Listener
@@ -138,10 +122,8 @@ public class HabitScoreView extends ScrollableDataView
else
{
if (habit == null) return;
- if (bucketSize == 1)
- scores = habit.getScores().getAll();
- else
- scores = habit.getScores().groupBy(getTruncateField());
+ if (bucketSize == 1) scores = habit.getScores().getAll();
+ else scores = habit.getScores().groupBy(getTruncateField());
createColors();
}
@@ -168,19 +150,6 @@ public class HabitScoreView extends ScrollableDataView
requestLayout();
}
- private void createColors()
- {
- if (habit != null) this.primaryColor =
- ColorUtils.getColor(getContext(), habit.getColor());
-
- textColor = InterfaceUtils.getStyledColor(getContext(),
- R.attr.mediumContrastTextColor);
- gridColor = InterfaceUtils.getStyledColor(getContext(),
- R.attr.lowContrastTextColor);
- backgroundColor = InterfaceUtils.getStyledColor(getContext(),
- R.attr.cardBackgroundColor);
- }
-
protected void createPaints()
{
pText = new Paint();
@@ -194,6 +163,158 @@ public class HabitScoreView extends ScrollableDataView
pGrid.setAntiAlias(true);
}
+ @Override
+ protected void onAttachedToWindow()
+ {
+ super.onAttachedToWindow();
+ new BaseTask()
+ {
+ @Override
+ protected void doInBackground()
+ {
+ refreshData();
+ }
+ }.execute();
+ habit.getObservable().addListener(this);
+ habit.getScores().getObservable().addListener(this);
+ }
+
+ @Override
+ protected void onDetachedFromWindow()
+ {
+ habit.getScores().getObservable().removeListener(this);
+ habit.getObservable().removeListener(this);
+ super.onDetachedFromWindow();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas)
+ {
+ super.onDraw(canvas);
+ Canvas activeCanvas;
+
+ if (isTransparencyEnabled)
+ {
+ if (drawingCache == null) initCache(getWidth(), getHeight());
+
+ activeCanvas = cacheCanvas;
+ drawingCache.eraseColor(Color.TRANSPARENT);
+ }
+ else
+ {
+ activeCanvas = canvas;
+ }
+
+ if (habit == null || scores == null) return;
+
+ rect.set(0, 0, nColumns * columnWidth, columnHeight);
+ rect.offset(0, paddingTop);
+
+ drawGrid(activeCanvas, rect);
+
+ pText.setColor(textColor);
+ pGraph.setColor(primaryColor);
+ prevRect.setEmpty();
+
+ previousMonthText = "";
+ previousYearText = "";
+ skipYear = 0;
+
+ long currentDate = DateUtils.getStartOfToday();
+
+ for (int k = 0; k < nColumns + getDataOffset() - 1; k++)
+ currentDate -= bucketSize * DateUtils.millisecondsInOneDay;
+
+ for (int k = 0; k < nColumns; k++)
+ {
+ int score = 0;
+ int offset = nColumns - k - 1 + getDataOffset();
+ if (offset < scores.size()) score = scores.get(offset).getValue();
+
+ double relativeScore = ((double) score) / Score.MAX_VALUE;
+ int height = (int) (columnHeight * relativeScore);
+
+ rect.set(0, 0, baseSize, baseSize);
+ rect.offset(k * columnWidth + (columnWidth - baseSize) / 2,
+ paddingTop + columnHeight - height - baseSize / 2);
+
+ if (!prevRect.isEmpty())
+ {
+ drawLine(activeCanvas, prevRect, rect);
+ drawMarker(activeCanvas, prevRect);
+ }
+
+ if (k == nColumns - 1) drawMarker(activeCanvas, rect);
+
+ prevRect.set(rect);
+ rect.set(0, 0, columnWidth, columnHeight);
+ rect.offset(k * columnWidth, paddingTop);
+
+ drawFooter(activeCanvas, rect, currentDate);
+
+ currentDate += bucketSize * DateUtils.millisecondsInOneDay;
+ }
+
+ if (activeCanvas != canvas) canvas.drawBitmap(drawingCache, 0, 0, null);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
+ {
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+ setMeasuredDimension(width, height);
+ }
+
+ @Override
+ protected void onSizeChanged(int width,
+ int height,
+ int oldWidth,
+ int oldHeight)
+ {
+ if (height < 9) height = 200;
+
+ float maxTextSize = getResources().getDimension(R.dimen.tinyTextSize);
+ float textSize = height * 0.06f;
+ pText.setTextSize(Math.min(textSize, maxTextSize));
+ em = pText.getFontSpacing();
+
+ footerHeight = (int) (3 * em);
+ paddingTop = (int) (em);
+
+ baseSize = (height - footerHeight - paddingTop) / 8;
+ setScrollerBucketSize(baseSize);
+
+ columnWidth = baseSize;
+ columnWidth = Math.max(columnWidth, getMaxDayWidth() * 1.5f);
+ columnWidth = Math.max(columnWidth, getMaxMonthWidth() * 1.2f);
+
+ nColumns = (int) (width / columnWidth);
+ columnWidth = (float) width / nColumns;
+
+ columnHeight = 8 * baseSize;
+
+ float minStrokeWidth = InterfaceUtils.dpToPixels(getContext(), 1);
+ pGraph.setTextSize(baseSize * 0.5f);
+ pGraph.setStrokeWidth(baseSize * 0.1f);
+ pGrid.setStrokeWidth(Math.min(minStrokeWidth, baseSize * 0.05f));
+
+ if (isTransparencyEnabled) initCache(width, height);
+ }
+
+ private void createColors()
+ {
+ if (habit != null) this.primaryColor =
+ ColorUtils.getColor(getContext(), habit.getColor());
+
+ textColor = InterfaceUtils.getStyledColor(getContext(),
+ R.attr.mediumContrastTextColor);
+ gridColor = InterfaceUtils.getStyledColor(getContext(),
+ R.attr.lowContrastTextColor);
+ backgroundColor = InterfaceUtils.getStyledColor(getContext(),
+ R.attr.cardBackgroundColor);
+ }
+
private void drawFooter(Canvas canvas, RectF rect, long currentDate)
{
String yearText = dfYear.format(currentDate);
@@ -393,145 +514,6 @@ public class HabitScoreView extends ScrollableDataView
cacheCanvas = new Canvas(drawingCache);
}
- @Override
- protected void onAttachedToWindow()
- {
- super.onAttachedToWindow();
- new BaseTask()
- {
- @Override
- protected void doInBackground()
- {
- refreshData();
- }
- }.execute();
- habit.getObservable().addListener(this);
- habit.getScores().getObservable().addListener(this);
- }
-
- @Override
- protected void onDetachedFromWindow()
- {
- habit.getScores().getObservable().removeListener(this);
- habit.getObservable().removeListener(this);
- super.onDetachedFromWindow();
- }
-
- @Override
- protected void onDraw(Canvas canvas)
- {
- super.onDraw(canvas);
- Canvas activeCanvas;
-
- if (isTransparencyEnabled)
- {
- if (drawingCache == null) initCache(getWidth(), getHeight());
-
- activeCanvas = cacheCanvas;
- drawingCache.eraseColor(Color.TRANSPARENT);
- }
- else
- {
- activeCanvas = canvas;
- }
-
- if (habit == null || scores == null) return;
-
- rect.set(0, 0, nColumns * columnWidth, columnHeight);
- rect.offset(0, paddingTop);
-
- drawGrid(activeCanvas, rect);
-
- pText.setColor(textColor);
- pGraph.setColor(primaryColor);
- prevRect.setEmpty();
-
- previousMonthText = "";
- previousYearText = "";
- skipYear = 0;
-
- long currentDate = DateUtils.getStartOfToday();
-
- for (int k = 0; k < nColumns + getDataOffset() - 1; k++)
- currentDate -= bucketSize * DateUtils.millisecondsInOneDay;
-
- for (int k = 0; k < nColumns; k++)
- {
- int score = 0;
- int offset = nColumns - k - 1 + getDataOffset();
- if (offset < scores.size()) score = scores.get(offset).getValue();
-
- double relativeScore = ((double) score) / Score.MAX_VALUE;
- int height = (int) (columnHeight * relativeScore);
-
- rect.set(0, 0, baseSize, baseSize);
- rect.offset(k * columnWidth + (columnWidth - baseSize) / 2,
- paddingTop + columnHeight - height - baseSize / 2);
-
- if (!prevRect.isEmpty())
- {
- drawLine(activeCanvas, prevRect, rect);
- drawMarker(activeCanvas, prevRect);
- }
-
- if (k == nColumns - 1) drawMarker(activeCanvas, rect);
-
- prevRect.set(rect);
- rect.set(0, 0, columnWidth, columnHeight);
- rect.offset(k * columnWidth, paddingTop);
-
- drawFooter(activeCanvas, rect, currentDate);
-
- currentDate += bucketSize * DateUtils.millisecondsInOneDay;
- }
-
- if (activeCanvas != canvas) canvas.drawBitmap(drawingCache, 0, 0, null);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
- {
- int width = MeasureSpec.getSize(widthMeasureSpec);
- int height = MeasureSpec.getSize(heightMeasureSpec);
- setMeasuredDimension(width, height);
- }
-
- @Override
- protected void onSizeChanged(int width,
- int height,
- int oldWidth,
- int oldHeight)
- {
- if (height < 9) height = 200;
-
- float maxTextSize = getResources().getDimension(R.dimen.tinyTextSize);
- float textSize = height * 0.06f;
- pText.setTextSize(Math.min(textSize, maxTextSize));
- em = pText.getFontSpacing();
-
- footerHeight = (int) (3 * em);
- paddingTop = (int) (em);
-
- baseSize = (height - footerHeight - paddingTop) / 8;
- setScrollerBucketSize(baseSize);
-
- columnWidth = baseSize;
- columnWidth = Math.max(columnWidth, getMaxDayWidth() * 1.5f);
- columnWidth = Math.max(columnWidth, getMaxMonthWidth() * 1.2f);
-
- nColumns = (int) (width / columnWidth);
- columnWidth = (float) width / nColumns;
-
- columnHeight = 8 * baseSize;
-
- float minStrokeWidth = InterfaceUtils.dpToPixels(getContext(), 1);
- pGraph.setTextSize(baseSize * 0.5f);
- pGraph.setStrokeWidth(baseSize * 0.1f);
- pGrid.setStrokeWidth(Math.min(minStrokeWidth, baseSize * 0.05f));
-
- if (isTransparencyEnabled) initCache(width, height);
- }
-
private void setModeOrColor(Paint p, PorterDuffXfermode mode, int color)
{
if (isTransparencyEnabled) p.setXfermode(mode);
diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitStreakView.java b/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitStreakView.java
index 59d2bc78..68ebdf93 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitStreakView.java
+++ b/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitStreakView.java
@@ -19,27 +19,18 @@
package org.isoron.uhabits.ui.habits.show.views;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.RectF;
-import android.util.AttributeSet;
-import android.view.View;
+import android.content.*;
+import android.graphics.*;
+import android.util.*;
+import android.view.*;
-import org.isoron.uhabits.R;
-import org.isoron.uhabits.models.Habit;
-import org.isoron.uhabits.models.ModelObservable;
-import org.isoron.uhabits.models.Streak;
-import org.isoron.uhabits.tasks.BaseTask;
-import org.isoron.uhabits.utils.ColorUtils;
-import org.isoron.uhabits.utils.InterfaceUtils;
+import org.isoron.uhabits.*;
+import org.isoron.uhabits.models.*;
+import org.isoron.uhabits.tasks.*;
+import org.isoron.uhabits.utils.*;
-import java.text.DateFormat;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.TimeZone;
+import java.text.*;
+import java.util.*;
public class HabitStreakView extends View
implements HabitDataView, ModelObservable.Listener
@@ -124,27 +115,6 @@ public class HabitStreakView extends View
createColors();
}
- private void createColors()
- {
- if (habit != null) this.primaryColor =
- ColorUtils.getColor(getContext(), habit.getColor());
-
- int red = Color.red(primaryColor);
- int green = Color.green(primaryColor);
- int blue = Color.blue(primaryColor);
-
- colors = new int[4];
- colors[3] = primaryColor;
- colors[2] = Color.argb(192, red, green, blue);
- colors[1] = Color.argb(96, red, green, blue);
- colors[0] = InterfaceUtils.getStyledColor(getContext(),
- R.attr.lowContrastTextColor);
- textColor = InterfaceUtils.getStyledColor(getContext(),
- R.attr.mediumContrastTextColor);
- reverseTextColor = InterfaceUtils.getStyledColor(getContext(),
- R.attr.highContrastReverseTextColor);
- }
-
protected void createPaints()
{
paint = new Paint();
@@ -152,62 +122,6 @@ public class HabitStreakView extends View
paint.setAntiAlias(true);
}
- private void drawRow(Canvas canvas, Streak streak, RectF rect)
- {
- if (maxLength == 0) return;
-
- float percentage = (float) streak.getLength() / maxLength;
- float availableWidth = width - 2 * maxLabelWidth;
- if (shouldShowLabels) availableWidth -= 2 * textMargin;
-
- float barWidth = percentage * availableWidth;
- float minBarWidth =
- paint.measureText(Long.toString(streak.getLength())) + em;
- barWidth = Math.max(barWidth, minBarWidth);
-
- float gap = (width - barWidth) / 2;
- float paddingTopBottom = baseSize * 0.05f;
-
- paint.setColor(percentageToColor(percentage));
-
- canvas.drawRect(rect.left + gap, rect.top + paddingTopBottom,
- rect.right - gap, rect.bottom - paddingTopBottom, paint);
-
- float yOffset = rect.centerY() + 0.3f * em;
-
- paint.setColor(reverseTextColor);
- paint.setTextAlign(Paint.Align.CENTER);
- canvas.drawText(Long.toString(streak.getLength()), rect.centerX(),
- yOffset, paint);
-
- if (shouldShowLabels)
- {
- String startLabel = dateFormat.format(new Date(streak.getStart()));
- String endLabel = dateFormat.format(new Date(streak.getEnd()));
-
- paint.setColor(textColor);
- paint.setTextAlign(Paint.Align.RIGHT);
- canvas.drawText(startLabel, gap - textMargin, yOffset, paint);
-
- paint.setTextAlign(Paint.Align.LEFT);
- canvas.drawText(endLabel, width - gap + textMargin, yOffset, paint);
- }
- }
-
- private void init()
- {
- createPaints();
- createColors();
-
- streaks = Collections.emptyList();
-
- dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM);
- dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
- rect = new RectF();
- maxStreakCount = 10;
- baseSize = getResources().getDimensionPixelSize(R.dimen.baseSize);
- }
-
@Override
protected void onAttachedToWindow()
{
@@ -277,6 +191,83 @@ public class HabitStreakView extends View
updateMaxMin();
}
+ private void createColors()
+ {
+ if (habit != null) this.primaryColor =
+ ColorUtils.getColor(getContext(), habit.getColor());
+
+ int red = Color.red(primaryColor);
+ int green = Color.green(primaryColor);
+ int blue = Color.blue(primaryColor);
+
+ colors = new int[4];
+ colors[3] = primaryColor;
+ colors[2] = Color.argb(192, red, green, blue);
+ colors[1] = Color.argb(96, red, green, blue);
+ colors[0] = InterfaceUtils.getStyledColor(getContext(),
+ R.attr.lowContrastTextColor);
+ textColor = InterfaceUtils.getStyledColor(getContext(),
+ R.attr.mediumContrastTextColor);
+ reverseTextColor = InterfaceUtils.getStyledColor(getContext(),
+ R.attr.highContrastReverseTextColor);
+ }
+
+ private void drawRow(Canvas canvas, Streak streak, RectF rect)
+ {
+ if (maxLength == 0) return;
+
+ float percentage = (float) streak.getLength() / maxLength;
+ float availableWidth = width - 2 * maxLabelWidth;
+ if (shouldShowLabels) availableWidth -= 2 * textMargin;
+
+ float barWidth = percentage * availableWidth;
+ float minBarWidth =
+ paint.measureText(Long.toString(streak.getLength())) + em;
+ barWidth = Math.max(barWidth, minBarWidth);
+
+ float gap = (width - barWidth) / 2;
+ float paddingTopBottom = baseSize * 0.05f;
+
+ paint.setColor(percentageToColor(percentage));
+
+ canvas.drawRect(rect.left + gap, rect.top + paddingTopBottom,
+ rect.right - gap, rect.bottom - paddingTopBottom, paint);
+
+ float yOffset = rect.centerY() + 0.3f * em;
+
+ paint.setColor(reverseTextColor);
+ paint.setTextAlign(Paint.Align.CENTER);
+ canvas.drawText(Long.toString(streak.getLength()), rect.centerX(),
+ yOffset, paint);
+
+ if (shouldShowLabels)
+ {
+ String startLabel = dateFormat.format(new Date(streak.getStart()));
+ String endLabel = dateFormat.format(new Date(streak.getEnd()));
+
+ paint.setColor(textColor);
+ paint.setTextAlign(Paint.Align.RIGHT);
+ canvas.drawText(startLabel, gap - textMargin, yOffset, paint);
+
+ paint.setTextAlign(Paint.Align.LEFT);
+ canvas.drawText(endLabel, width - gap + textMargin, yOffset, paint);
+ }
+ }
+
+ private void init()
+ {
+ createPaints();
+ createColors();
+
+ streaks = Collections.emptyList();
+
+ dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM);
+ dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
+ rect = new RectF();
+ maxStreakCount = 10;
+ baseSize = getResources().getDimensionPixelSize(R.dimen.baseSize);
+ }
+
private int percentageToColor(float percentage)
{
if (percentage >= 1.0f) return colors[3];
diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/RingView.java b/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/RingView.java
index f471dfce..2d124fe6 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/RingView.java
+++ b/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/RingView.java
@@ -19,47 +19,52 @@
package org.isoron.uhabits.ui.habits.show.views;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.RectF;
-import android.support.annotation.Nullable;
-import android.text.TextPaint;
-import android.util.AttributeSet;
-import android.view.View;
+import android.content.*;
+import android.graphics.*;
+import android.support.annotation.*;
+import android.text.*;
+import android.util.*;
+import android.view.*;
-import org.isoron.uhabits.R;
-import org.isoron.uhabits.utils.ColorUtils;
-import org.isoron.uhabits.utils.InterfaceUtils;
+import org.isoron.uhabits.*;
+import org.isoron.uhabits.utils.*;
+
+import static org.isoron.uhabits.utils.InterfaceUtils.*;
public class RingView extends View
{
public static final PorterDuffXfermode XFERMODE_CLEAR =
- new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
+ new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
private int color;
+
private float precision;
+
private float percentage;
+
private int diameter;
+
private float thickness;
private RectF rect;
+
private TextPaint pRing;
private Integer backgroundColor;
+
private Integer inactiveColor;
private float em;
+
private String text;
+
private float textSize;
+
private boolean enableFontAwesome;
@Nullable
private Bitmap drawingCache;
+
private Canvas cacheCanvas;
private boolean isTransparencyEnabled;
@@ -71,54 +76,56 @@ public class RingView extends View
percentage = 0.0f;
precision = 0.01f;
color = ColorUtils.getAndroidTestColor(0);
- thickness = InterfaceUtils.dpToPixels(getContext(), 2);
+ thickness = dpToPixels(getContext(), 2);
text = "";
textSize = context.getResources().getDimension(R.dimen.smallTextSize);
init();
}
- public RingView(Context context, AttributeSet attrs)
+ public RingView(Context ctx, AttributeSet attrs)
{
- super(context, attrs);
+ super(ctx, attrs);
- percentage = InterfaceUtils.getFloatAttribute(context, attrs, "percentage", 0);
- precision = InterfaceUtils.getFloatAttribute(context, attrs, "precision", 0.01f);
+ percentage = getFloatAttribute(ctx, attrs, "percentage", 0);
+ precision = getFloatAttribute(ctx, attrs, "precision", 0.01f);
- color = InterfaceUtils.getColorAttribute(context, attrs, "color", 0);
- backgroundColor = InterfaceUtils.getColorAttribute(context, attrs, "backgroundColor", null);
- inactiveColor = InterfaceUtils.getColorAttribute(context, attrs, "inactiveColor", null);
+ color = getColorAttribute(ctx, attrs, "color", 0);
+ backgroundColor =
+ getColorAttribute(ctx, attrs, "backgroundColor", null);
+ inactiveColor = getColorAttribute(ctx, attrs, "inactiveColor", null);
- thickness = InterfaceUtils.getFloatAttribute(context, attrs, "thickness", 0);
- thickness = InterfaceUtils.dpToPixels(context, thickness);
+ thickness = getFloatAttribute(ctx, attrs, "thickness", 0);
+ thickness = dpToPixels(ctx, thickness);
- float defaultTextSize = context.getResources().getDimension(R.dimen.smallTextSize);
- textSize = InterfaceUtils.getFloatAttribute(context, attrs, "textSize", defaultTextSize);
- textSize = InterfaceUtils.spToPixels(context, textSize);
+ float defaultTextSize =
+ ctx.getResources().getDimension(R.dimen.smallTextSize);
+ textSize = getFloatAttribute(ctx, attrs, "textSize", defaultTextSize);
+ textSize = spToPixels(ctx, textSize);
+ text = getAttribute(ctx, attrs, "text", "");
- text = InterfaceUtils.getAttribute(context, attrs, "text", "");
-
- enableFontAwesome = InterfaceUtils.getBooleanAttribute(context, attrs, "enableFontAwesome", false);
+ enableFontAwesome =
+ getBooleanAttribute(ctx, attrs, "enableFontAwesome", false);
init();
}
+ @Override
+ public void setBackgroundColor(int backgroundColor)
+ {
+ this.backgroundColor = backgroundColor;
+ postInvalidate();
+ }
+
public void setColor(int color)
{
this.color = color;
postInvalidate();
}
- public void setTextSize(float textSize)
+ public void setIsTransparencyEnabled(boolean isTransparencyEnabled)
{
- this.textSize = textSize;
- }
-
- @Override
- public void setBackgroundColor(int backgroundColor)
- {
- this.backgroundColor = backgroundColor;
- postInvalidate();
+ this.isTransparencyEnabled = isTransparencyEnabled;
}
public void setPercentage(float percentage)
@@ -133,34 +140,68 @@ public class RingView extends View
postInvalidate();
}
- public void setThickness(float thickness)
- {
- this.thickness = thickness;
- postInvalidate();
- }
-
public void setText(String text)
{
this.text = text;
postInvalidate();
}
- private void init()
+ public void setTextSize(float textSize)
{
- pRing = new TextPaint();
- pRing.setAntiAlias(true);
+ this.textSize = textSize;
+ }
+
+ public void setThickness(float thickness)
+ {
+ this.thickness = thickness;
+ postInvalidate();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas)
+ {
+ super.onDraw(canvas);
+ Canvas activeCanvas;
+
+ if (isTransparencyEnabled)
+ {
+ if (drawingCache == null) reallocateCache();
+ activeCanvas = cacheCanvas;
+ drawingCache.eraseColor(Color.TRANSPARENT);
+ }
+ else
+ {
+ activeCanvas = canvas;
+ }
+
pRing.setColor(color);
- pRing.setTextAlign(Paint.Align.CENTER);
+ rect.set(0, 0, diameter, diameter);
- if(backgroundColor == null)
- backgroundColor = InterfaceUtils.getStyledColor(getContext(), R.attr.cardBackgroundColor);
+ float angle = 360 * Math.round(percentage / precision) * precision;
- if(inactiveColor == null)
- inactiveColor = InterfaceUtils.getStyledColor(getContext(), R.attr.highContrastTextColor);
+ activeCanvas.drawArc(rect, -90, angle, true, pRing);
- inactiveColor = ColorUtils.setAlpha(inactiveColor, 0.1f);
+ pRing.setColor(inactiveColor);
+ activeCanvas.drawArc(rect, angle - 90, 360 - angle, true, pRing);
- rect = new RectF();
+ if (thickness > 0)
+ {
+ if (isTransparencyEnabled) pRing.setXfermode(XFERMODE_CLEAR);
+ else pRing.setColor(backgroundColor);
+
+ rect.inset(thickness, thickness);
+ activeCanvas.drawArc(rect, 0, 360, true, pRing);
+ pRing.setXfermode(null);
+
+ pRing.setColor(color);
+ pRing.setTextSize(textSize);
+ if (enableFontAwesome)
+ pRing.setTypeface(getFontAwesome(getContext()));
+ activeCanvas.drawText(text, rect.centerX(),
+ rect.centerY() + 0.4f * em, pRing);
+ }
+
+ if (activeCanvas != canvas) canvas.drawBitmap(drawingCache, 0, 0, null);
}
@Override
@@ -183,66 +224,34 @@ public class RingView extends View
{
super.onSizeChanged(w, h, oldw, oldh);
- if(isTransparencyEnabled) reallocateCache();
+ if (isTransparencyEnabled) reallocateCache();
+ }
+
+ private void init()
+ {
+ pRing = new TextPaint();
+ pRing.setAntiAlias(true);
+ pRing.setColor(color);
+ pRing.setTextAlign(Paint.Align.CENTER);
+
+ if (backgroundColor == null) backgroundColor =
+ InterfaceUtils.getStyledColor(getContext(),
+ R.attr.cardBackgroundColor);
+
+ if (inactiveColor == null) inactiveColor =
+ InterfaceUtils.getStyledColor(getContext(),
+ R.attr.highContrastTextColor);
+
+ inactiveColor = ColorUtils.setAlpha(inactiveColor, 0.1f);
+
+ rect = new RectF();
}
private void reallocateCache()
{
if (drawingCache != null) drawingCache.recycle();
- drawingCache = Bitmap.createBitmap(diameter, diameter, Bitmap.Config.ARGB_8888);
+ drawingCache =
+ Bitmap.createBitmap(diameter, diameter, Bitmap.Config.ARGB_8888);
cacheCanvas = new Canvas(drawingCache);
}
-
- @Override
- protected void onDraw(Canvas canvas)
- {
- super.onDraw(canvas);
- Canvas activeCanvas;
-
- if(isTransparencyEnabled)
- {
- if(drawingCache == null) reallocateCache();
- activeCanvas = cacheCanvas;
- drawingCache.eraseColor(Color.TRANSPARENT);
- }
- else
- {
- activeCanvas = canvas;
- }
-
- pRing.setColor(color);
- rect.set(0, 0, diameter, diameter);
-
- float angle = 360 * Math.round(percentage / precision) * precision;
-
- activeCanvas.drawArc(rect, -90, angle, true, pRing);
-
- pRing.setColor(inactiveColor);
- activeCanvas.drawArc(rect, angle - 90, 360 - angle, true, pRing);
-
- if(thickness > 0)
- {
- if(isTransparencyEnabled)
- pRing.setXfermode(XFERMODE_CLEAR);
- else
- pRing.setColor(backgroundColor);
-
- rect.inset(thickness, thickness);
- activeCanvas.drawArc(rect, 0, 360, true, pRing);
- pRing.setXfermode(null);
-
- pRing.setColor(color);
- pRing.setTextSize(textSize);
- if(enableFontAwesome) pRing.setTypeface(InterfaceUtils.getFontAwesome(getContext()));
- activeCanvas.drawText(text, rect.centerX(), rect.centerY() + 0.4f * em, pRing);
- }
-
- if(activeCanvas != canvas)
- canvas.drawBitmap(drawingCache, 0, 0, null);
- }
-
- public void setIsTransparencyEnabled(boolean isTransparencyEnabled)
- {
- this.isTransparencyEnabled = isTransparencyEnabled;
- }
}
diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/ScrollableDataView.java b/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/ScrollableDataView.java
index 746d06cd..09fa9dd9 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/ScrollableDataView.java
+++ b/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/ScrollableDataView.java
@@ -19,14 +19,11 @@
package org.isoron.uhabits.ui.habits.show.views;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewParent;
-import android.widget.Scroller;
+import android.animation.*;
+import android.content.*;
+import android.util.*;
+import android.view.*;
+import android.widget.*;
public abstract class ScrollableDataView extends View
implements GestureDetector.OnGestureListener,
diff --git a/app/src/main/java/org/isoron/uhabits/ui/settings/SettingsActivity.java b/app/src/main/java/org/isoron/uhabits/ui/settings/SettingsActivity.java
index c281f23d..24198dc7 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/settings/SettingsActivity.java
+++ b/app/src/main/java/org/isoron/uhabits/ui/settings/SettingsActivity.java
@@ -20,6 +20,9 @@
package org.isoron.uhabits.ui.settings;
import android.os.*;
+import android.support.annotation.*;
+import android.support.v4.app.*;
+import android.view.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.ui.*;
diff --git a/app/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkWidgetView.java b/app/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkWidgetView.java
index 47a8b258..d1893d53 100644
--- a/app/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkWidgetView.java
+++ b/app/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkWidgetView.java
@@ -31,7 +31,6 @@ import org.isoron.uhabits.models.Checkmark;
import org.isoron.uhabits.models.Habit;
import org.isoron.uhabits.models.Score;
import org.isoron.uhabits.ui.habits.show.views.HabitDataView;
-import org.isoron.uhabits.ui.habits.show.views.HabitWidgetView;
import org.isoron.uhabits.ui.habits.show.views.RingView;
import org.isoron.uhabits.utils.ColorUtils;
import org.isoron.uhabits.utils.InterfaceUtils;
diff --git a/app/src/main/java/org/isoron/uhabits/widgets/views/GraphWidgetView.java b/app/src/main/java/org/isoron/uhabits/widgets/views/GraphWidgetView.java
index 4198d84b..621e00b1 100644
--- a/app/src/main/java/org/isoron/uhabits/widgets/views/GraphWidgetView.java
+++ b/app/src/main/java/org/isoron/uhabits/widgets/views/GraphWidgetView.java
@@ -28,7 +28,6 @@ import android.widget.TextView;
import org.isoron.uhabits.R;
import org.isoron.uhabits.models.Habit;
import org.isoron.uhabits.ui.habits.show.views.HabitDataView;
-import org.isoron.uhabits.ui.habits.show.views.HabitWidgetView;
public class GraphWidgetView extends HabitWidgetView implements HabitDataView
{
diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitWidgetView.java b/app/src/main/java/org/isoron/uhabits/widgets/views/HabitWidgetView.java
similarity index 66%
rename from app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitWidgetView.java
rename to app/src/main/java/org/isoron/uhabits/widgets/views/HabitWidgetView.java
index 6b161f01..f7ca8131 100644
--- a/app/src/main/java/org/isoron/uhabits/ui/habits/show/views/HabitWidgetView.java
+++ b/app/src/main/java/org/isoron/uhabits/widgets/views/HabitWidgetView.java
@@ -17,27 +17,26 @@
* with this program. If not, see .
*/
-package org.isoron.uhabits.ui.habits.show.views;
+package org.isoron.uhabits.widgets.views;
-import android.content.Context;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.drawable.InsetDrawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.RoundRectShape;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.AttributeSet;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
+import android.content.*;
+import android.graphics.*;
+import android.graphics.drawable.*;
+import android.graphics.drawable.shapes.*;
+import android.support.annotation.*;
+import android.util.*;
+import android.view.*;
+import android.widget.*;
-import org.isoron.uhabits.R;
-import org.isoron.uhabits.models.Habit;
-import org.isoron.uhabits.utils.InterfaceUtils;
+import org.isoron.uhabits.*;
+import org.isoron.uhabits.models.*;
+import org.isoron.uhabits.ui.habits.show.views.*;
+import org.isoron.uhabits.utils.*;
-import java.util.Arrays;
+import java.util.*;
-public abstract class HabitWidgetView extends FrameLayout implements HabitDataView
+public abstract class HabitWidgetView extends FrameLayout
+ implements HabitDataView
{
@Nullable
protected InsetDrawable background;
@@ -47,12 +46,8 @@ public abstract class HabitWidgetView extends FrameLayout implements HabitDataV
@Nullable
protected Habit habit;
- protected ViewGroup frame;
- public void setShadowAlpha(int shadowAlpha)
- {
- this.shadowAlpha = shadowAlpha;
- }
+ protected ViewGroup frame;
private int shadowAlpha;
@@ -68,21 +63,28 @@ public abstract class HabitWidgetView extends FrameLayout implements HabitDataV
init();
}
- private void init()
+ @Override
+ public void setHabit(@NonNull Habit habit)
{
- inflate(getContext(), getInnerLayoutId(), this);
- shadowAlpha = (int) (255 * InterfaceUtils.getStyledFloat(getContext(), R.attr.widgetShadowAlpha));
- rebuildBackground();
+ this.habit = habit;
}
- protected abstract @NonNull Integer getInnerLayoutId();
+ public void setShadowAlpha(int shadowAlpha)
+ {
+ this.shadowAlpha = shadowAlpha;
+ }
+
+ protected abstract
+ @NonNull
+ Integer getInnerLayoutId();
protected void rebuildBackground()
{
Context context = getContext();
- int backgroundAlpha =
- (int) (255 * InterfaceUtils.getStyledFloat(context, R.attr.widgetBackgroundAlpha));
+ int backgroundAlpha = (int) (255 *
+ InterfaceUtils.getStyledFloat(context,
+ R.attr.widgetBackgroundAlpha));
int shadowRadius = (int) InterfaceUtils.dpToPixels(context, 2);
int shadowOffset = (int) InterfaceUtils.dpToPixels(context, 1);
@@ -98,20 +100,25 @@ public abstract class HabitWidgetView extends FrameLayout implements HabitDataV
int insetLeftTop = Math.max(shadowRadius - shadowOffset, 0);
int insetRightBottom = shadowRadius + shadowOffset;
- background = new InsetDrawable(innerDrawable, insetLeftTop, insetLeftTop, insetRightBottom,
- insetRightBottom);
+ background =
+ new InsetDrawable(innerDrawable, insetLeftTop, insetLeftTop,
+ insetRightBottom, insetRightBottom);
backgroundPaint = innerDrawable.getPaint();
- backgroundPaint.setShadowLayer(shadowRadius, shadowOffset, shadowOffset, shadowColor);
- backgroundPaint.setColor(InterfaceUtils.getStyledColor(context, R.attr.cardBackgroundColor));
+ backgroundPaint.setShadowLayer(shadowRadius, shadowOffset, shadowOffset,
+ shadowColor);
+ backgroundPaint.setColor(
+ InterfaceUtils.getStyledColor(context, R.attr.cardBackgroundColor));
backgroundPaint.setAlpha(backgroundAlpha);
frame = (ViewGroup) findViewById(R.id.frame);
- if(frame != null) frame.setBackgroundDrawable(background);
+ if (frame != null) frame.setBackgroundDrawable(background);
}
- @Override
- public void setHabit(@NonNull Habit habit)
+ private void init()
{
- this.habit = habit;
+ inflate(getContext(), getInnerLayoutId(), this);
+ shadowAlpha = (int) (255 * InterfaceUtils.getStyledFloat(getContext(),
+ R.attr.widgetShadowAlpha));
+ rebuildBackground();
}
}