mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Reformat and reorganize some code
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -111,13 +111,6 @@ public class HabitCardListView extends DragSortListView
|
||||
});
|
||||
}
|
||||
|
||||
public void toggleShowArchived()
|
||||
{
|
||||
// showArchived = !showArchived;
|
||||
// cache.setIncludeArchived(showArchived);
|
||||
// cache.refreshAllHabits(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow()
|
||||
{
|
||||
|
||||
@@ -33,7 +33,7 @@ import javax.inject.*;
|
||||
|
||||
/**
|
||||
* Activity that allows the user to see more information about a single habit.
|
||||
*
|
||||
* <p>
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,16 +195,11 @@ public class ShowHabitFragment extends Fragment
|
||||
public void onModelChange()
|
||||
{
|
||||
refreshData();
|
||||
activity.runOnUiThread(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
activity.runOnUiThread(() -> {
|
||||
helper.updateColors();
|
||||
helper.updateMainHeader(getView());
|
||||
helper.updateCardHeaders(getView());
|
||||
if (activity != null) activity.setupHabitActionBar();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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(),
|
||||
ColorUtils.getColor(fragment.activity, fragment.habit.getColor());
|
||||
textView.setTextColor(androidColor);
|
||||
}
|
||||
|
||||
void updateColors()
|
||||
{
|
||||
fragment.activeColor = ColorUtils.getColor(fragment.getContext(),
|
||||
fragment.habit.getColor());
|
||||
scoreRing.setColor(androidColor);
|
||||
scoreRing.setPercentage(todayPercentage);
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
void updateColors()
|
||||
{
|
||||
fragment.activeColor =
|
||||
ColorUtils.getColor(fragment.getContext(),
|
||||
RingView scoreRing = (RingView) view.findViewById(R.id.scoreRing);
|
||||
int androidColor = ColorUtils.getColor(fragment.getActivity(),
|
||||
fragment.habit.getColor());
|
||||
fragment.inactiveColor =
|
||||
InterfaceUtils.getStyledColor(fragment.getContext(),
|
||||
R.attr.mediumContrastTextColor);
|
||||
scoreRing.setColor(androidColor);
|
||||
scoreRing.setPercentage(todayPercentage);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Long, Integer[]> 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()
|
||||
@@ -129,78 +128,27 @@ public class HabitFrequencyView extends ScrollableDataView implements HabitDataV
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||
protected void onAttachedToWindow()
|
||||
{
|
||||
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
setMeasuredDimension(width, height);
|
||||
super.onAttachedToWindow();
|
||||
new BaseTask()
|
||||
{
|
||||
@Override
|
||||
protected void doInBackground()
|
||||
{
|
||||
refreshData();
|
||||
}
|
||||
}.execute();
|
||||
habit.getObservable().addListener(this);
|
||||
habit.getCheckmarks().observable.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
|
||||
protected void onDetachedFromWindow()
|
||||
{
|
||||
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);
|
||||
}
|
||||
habit.getCheckmarks().observable.removeListener(this);
|
||||
habit.getObservable().removeListener(this);
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -233,6 +181,59 @@ public class HabitFrequencyView extends ScrollableDataView implements HabitDataV
|
||||
}
|
||||
}
|
||||
|
||||
@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());
|
||||
@@ -246,8 +247,7 @@ public class HabitFrequencyView extends ScrollableDataView implements HabitDataV
|
||||
rect.offset(prevRect.left, prevRect.top + baseSize * j);
|
||||
|
||||
int i = DateUtils.javaWeekdayToLoopWeekday(localeWeekdayList[j]);
|
||||
if(values != null)
|
||||
drawMarker(canvas, rect, values[i]);
|
||||
if (values != null) drawMarker(canvas, rect, values[i]);
|
||||
|
||||
rect.offset(0, rowHeight);
|
||||
}
|
||||
@@ -259,19 +259,12 @@ public class HabitFrequencyView extends ScrollableDataView implements HabitDataV
|
||||
{
|
||||
Date time = date.getTime();
|
||||
|
||||
canvas.drawText(dfMonth.format(time), rect.centerX(), rect.centerY() - 0.1f * em, pText);
|
||||
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);
|
||||
canvas.drawText(dfYear.format(time), rect.centerX(),
|
||||
rect.centerY() + 0.9f * em, pText);
|
||||
}
|
||||
|
||||
private void drawGrid(Canvas canvas, RectF rGrid)
|
||||
@@ -283,12 +276,14 @@ public class HabitFrequencyView extends ScrollableDataView implements HabitDataV
|
||||
pText.setColor(textColor);
|
||||
pGrid.setColor(gridColor);
|
||||
|
||||
for (String day : DateUtils.getLocaleDayNames(Calendar.SHORT)) {
|
||||
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);
|
||||
canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top,
|
||||
pGrid);
|
||||
|
||||
rGrid.offset(0, rowHeight);
|
||||
}
|
||||
@@ -296,40 +291,58 @@ public class HabitFrequencyView extends ScrollableDataView implements HabitDataV
|
||||
canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top, pGrid);
|
||||
}
|
||||
|
||||
public void setIsBackgroundTransparent(boolean isBackgroundTransparent)
|
||||
private void drawMarker(Canvas canvas, RectF rect, Integer value)
|
||||
{
|
||||
this.isBackgroundTransparent = isBackgroundTransparent;
|
||||
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");
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow()
|
||||
{
|
||||
super.onAttachedToWindow();
|
||||
new BaseTask()
|
||||
{
|
||||
@Override
|
||||
protected void doInBackground()
|
||||
{
|
||||
refreshData();
|
||||
}
|
||||
}.execute();
|
||||
habit.getObservable().addListener(this);
|
||||
habit.getCheckmarks().observable.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow()
|
||||
{
|
||||
habit.getCheckmarks().observable.removeListener(this);
|
||||
habit.getObservable().removeListener(this);
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModelChange()
|
||||
{
|
||||
refreshData();
|
||||
rect = new RectF();
|
||||
prevRect = new RectF();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,269 +101,18 @@ 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)
|
||||
{
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -19,22 +19,17 @@
|
||||
|
||||
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
|
||||
{
|
||||
@@ -42,24 +37,34 @@ public class RingView extends View
|
||||
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,64 +140,21 @@ 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);
|
||||
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();
|
||||
this.textSize = textSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||
public void setThickness(float thickness)
|
||||
{
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
diameter = Math.min(height, width);
|
||||
|
||||
pRing.setTextSize(textSize);
|
||||
em = pRing.measureText("M");
|
||||
|
||||
setMeasuredDimension(diameter, diameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh)
|
||||
{
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
|
||||
if(isTransparencyEnabled) reallocateCache();
|
||||
}
|
||||
|
||||
private void reallocateCache()
|
||||
{
|
||||
if (drawingCache != null) drawingCache.recycle();
|
||||
drawingCache = Bitmap.createBitmap(diameter, diameter, Bitmap.Config.ARGB_8888);
|
||||
cacheCanvas = new Canvas(drawingCache);
|
||||
this.thickness = thickness;
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -222,10 +186,8 @@ public class RingView extends View
|
||||
|
||||
if (thickness > 0)
|
||||
{
|
||||
if(isTransparencyEnabled)
|
||||
pRing.setXfermode(XFERMODE_CLEAR);
|
||||
else
|
||||
pRing.setColor(backgroundColor);
|
||||
if (isTransparencyEnabled) pRing.setXfermode(XFERMODE_CLEAR);
|
||||
else pRing.setColor(backgroundColor);
|
||||
|
||||
rect.inset(thickness, thickness);
|
||||
activeCanvas.drawArc(rect, 0, 360, true, pRing);
|
||||
@@ -233,16 +195,63 @@ public class RingView extends View
|
||||
|
||||
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 (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);
|
||||
if (activeCanvas != canvas) canvas.drawBitmap(drawingCache, 0, 0, null);
|
||||
}
|
||||
|
||||
public void setIsTransparencyEnabled(boolean isTransparencyEnabled)
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||
{
|
||||
this.isTransparencyEnabled = isTransparencyEnabled;
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
diameter = Math.min(height, width);
|
||||
|
||||
pRing.setTextSize(textSize);
|
||||
em = pRing.measureText("M");
|
||||
|
||||
setMeasuredDimension(diameter, diameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh)
|
||||
{
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
|
||||
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);
|
||||
cacheCanvas = new Canvas(drawingCache);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.*;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -17,27 +17,26 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user