mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-07 01:28:52 -06:00
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of Loop Habit Tracker.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.dialogs;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.app.DialogFragment;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.R;
|
||||||
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
import org.isoron.uhabits.views.HabitHistoryView;
|
||||||
|
|
||||||
|
public class HistoryEditorDialog extends DialogFragment
|
||||||
|
implements DialogInterface.OnClickListener
|
||||||
|
{
|
||||||
|
private Habit habit;
|
||||||
|
private Listener listener;
|
||||||
|
HabitHistoryView historyView;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
Context context = getActivity();
|
||||||
|
historyView = new HabitHistoryView(context, null);
|
||||||
|
int p = (int) getResources().getDimension(R.dimen.history_editor_padding);
|
||||||
|
|
||||||
|
if(savedInstanceState != null)
|
||||||
|
{
|
||||||
|
long id = savedInstanceState.getLong("habit", -1);
|
||||||
|
if(id > 0) this.habit = Habit.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
historyView.setPadding(p, 0, p, 0);
|
||||||
|
historyView.setHabit(habit);
|
||||||
|
historyView.setIsEditable(true);
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
|
builder.setTitle("History Editor")
|
||||||
|
.setView(historyView)
|
||||||
|
.setPositiveButton(android.R.string.ok, this);
|
||||||
|
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume()
|
||||||
|
{
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
DisplayMetrics metrics = getResources().getDisplayMetrics();
|
||||||
|
int maxHeight = getResources().getDimensionPixelSize(R.dimen.history_editor_max_height);
|
||||||
|
int width = metrics.widthPixels;
|
||||||
|
int height = Math.min(metrics.heightPixels, maxHeight);
|
||||||
|
|
||||||
|
Log.d("HistoryEditorDialog", String.format("h=%d max_h=%d", height, maxHeight));
|
||||||
|
|
||||||
|
getDialog().getWindow().setLayout(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which)
|
||||||
|
{
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHabit(Habit habit)
|
||||||
|
{
|
||||||
|
this.habit = habit;
|
||||||
|
if(historyView != null) historyView.setHabit(habit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause()
|
||||||
|
{
|
||||||
|
super.onPause();
|
||||||
|
if(listener != null) listener.onHistoryEditorClosed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(Bundle outState)
|
||||||
|
{
|
||||||
|
outState.putLong("habit", habit.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setListener(Listener listener)
|
||||||
|
{
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Listener {
|
||||||
|
void onHistoryEditorClosed();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ import android.view.MenuInflater;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.isoron.helpers.ColorHelper;
|
import org.isoron.helpers.ColorHelper;
|
||||||
@@ -35,6 +36,7 @@ import org.isoron.helpers.Command;
|
|||||||
import org.isoron.helpers.DialogHelper;
|
import org.isoron.helpers.DialogHelper;
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.ShowHabitActivity;
|
import org.isoron.uhabits.ShowHabitActivity;
|
||||||
|
import org.isoron.uhabits.dialogs.HistoryEditorDialog;
|
||||||
import org.isoron.uhabits.helpers.ReminderHelper;
|
import org.isoron.uhabits.helpers.ReminderHelper;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
import org.isoron.uhabits.models.Score;
|
import org.isoron.uhabits.models.Score;
|
||||||
@@ -43,10 +45,14 @@ import org.isoron.uhabits.views.HabitScoreView;
|
|||||||
import org.isoron.uhabits.views.HabitStreakView;
|
import org.isoron.uhabits.views.HabitStreakView;
|
||||||
import org.isoron.uhabits.views.RingView;
|
import org.isoron.uhabits.views.RingView;
|
||||||
|
|
||||||
public class ShowHabitFragment extends Fragment implements DialogHelper.OnSavedListener
|
public class ShowHabitFragment extends Fragment
|
||||||
|
implements DialogHelper.OnSavedListener, HistoryEditorDialog.Listener
|
||||||
{
|
{
|
||||||
protected ShowHabitActivity activity;
|
protected ShowHabitActivity activity;
|
||||||
private Habit habit;
|
private Habit habit;
|
||||||
|
private HabitStreakView streakView;
|
||||||
|
private HabitScoreView scoreView;
|
||||||
|
private HabitHistoryView historyView;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart()
|
public void onStart()
|
||||||
@@ -64,6 +70,54 @@ public class ShowHabitFragment extends Fragment implements DialogHelper.OnSavedL
|
|||||||
|
|
||||||
habit.checkmarks.rebuild();
|
habit.checkmarks.rebuild();
|
||||||
|
|
||||||
|
Button btEditHistory = (Button) view.findViewById(R.id.btEditHistory);
|
||||||
|
streakView = (HabitStreakView) view.findViewById(R.id.streakView);
|
||||||
|
scoreView = (HabitScoreView) view.findViewById(R.id.scoreView);
|
||||||
|
historyView = (HabitHistoryView) view.findViewById(R.id.historyView);
|
||||||
|
|
||||||
|
updateHeaders(view);
|
||||||
|
updateScoreRing(view);
|
||||||
|
|
||||||
|
streakView.setHabit(habit);
|
||||||
|
scoreView.setHabit(habit);
|
||||||
|
historyView.setHabit(habit);
|
||||||
|
|
||||||
|
btEditHistory.setOnClickListener(new View.OnClickListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onClick(View v)
|
||||||
|
{
|
||||||
|
HistoryEditorDialog frag = new HistoryEditorDialog();
|
||||||
|
frag.setHabit(habit);
|
||||||
|
frag.setListener(ShowHabitFragment.this);
|
||||||
|
frag.show(getFragmentManager(), "historyEditor");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(savedInstanceState != null)
|
||||||
|
{
|
||||||
|
EditHabitFragment fragEdit = (EditHabitFragment) getFragmentManager()
|
||||||
|
.findFragmentByTag("editHabit");
|
||||||
|
HistoryEditorDialog fragEditor = (HistoryEditorDialog) getFragmentManager()
|
||||||
|
.findFragmentByTag("historyEditor");
|
||||||
|
|
||||||
|
if(fragEdit != null) fragEdit.setOnSavedListener(this);
|
||||||
|
if(fragEditor != null) fragEditor.setListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
setHasOptionsMenu(true);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateScoreRing(View view)
|
||||||
|
{
|
||||||
|
RingView scoreRing = (RingView) view.findViewById(R.id.scoreRing);
|
||||||
|
scoreRing.setColor(habit.color);
|
||||||
|
scoreRing.setPercentage((float) habit.scores.getNewestValue() / Score.MAX_SCORE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateHeaders(View view)
|
||||||
|
{
|
||||||
if (android.os.Build.VERSION.SDK_INT >= 21)
|
if (android.os.Build.VERSION.SDK_INT >= 21)
|
||||||
{
|
{
|
||||||
int darkerHabitColor = ColorHelper.mixColors(habit.color, Color.BLACK, 0.75f);
|
int darkerHabitColor = ColorHelper.mixColors(habit.color, Color.BLACK, 0.75f);
|
||||||
@@ -74,24 +128,10 @@ public class ShowHabitFragment extends Fragment implements DialogHelper.OnSavedL
|
|||||||
TextView tvOverview = (TextView) view.findViewById(R.id.tvOverview);
|
TextView tvOverview = (TextView) view.findViewById(R.id.tvOverview);
|
||||||
TextView tvStrength = (TextView) view.findViewById(R.id.tvStrength);
|
TextView tvStrength = (TextView) view.findViewById(R.id.tvStrength);
|
||||||
TextView tvStreaks = (TextView) view.findViewById(R.id.tvStreaks);
|
TextView tvStreaks = (TextView) view.findViewById(R.id.tvStreaks);
|
||||||
RingView scoreRing = (RingView) view.findViewById(R.id.scoreRing);
|
|
||||||
HabitStreakView streakView = (HabitStreakView) view.findViewById(R.id.streakView);
|
|
||||||
HabitScoreView scoreView = (HabitScoreView) view.findViewById(R.id.scoreView);
|
|
||||||
HabitHistoryView historyView = (HabitHistoryView) view.findViewById(R.id.historyView);
|
|
||||||
|
|
||||||
tvHistory.setTextColor(habit.color);
|
tvHistory.setTextColor(habit.color);
|
||||||
tvOverview.setTextColor(habit.color);
|
tvOverview.setTextColor(habit.color);
|
||||||
tvStrength.setTextColor(habit.color);
|
tvStrength.setTextColor(habit.color);
|
||||||
tvStreaks.setTextColor(habit.color);
|
tvStreaks.setTextColor(habit.color);
|
||||||
|
|
||||||
scoreRing.setColor(habit.color);
|
|
||||||
scoreRing.setPercentage((float) habit.scores.getNewestValue() / Score.MAX_SCORE);
|
|
||||||
streakView.setHabit(habit);
|
|
||||||
scoreView.setHabit(habit);
|
|
||||||
historyView.setHabit(habit);
|
|
||||||
|
|
||||||
setHasOptionsMenu(true);
|
|
||||||
return view;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -109,7 +149,7 @@ public class ShowHabitFragment extends Fragment implements DialogHelper.OnSavedL
|
|||||||
{
|
{
|
||||||
EditHabitFragment frag = EditHabitFragment.editSingleHabitFragment(habit.getId());
|
EditHabitFragment frag = EditHabitFragment.editSingleHabitFragment(habit.getId());
|
||||||
frag.setOnSavedListener(this);
|
frag.setOnSavedListener(this);
|
||||||
frag.show(getFragmentManager(), "dialog");
|
frag.show(getFragmentManager(), "editHabit");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,4 +168,18 @@ public class ShowHabitFragment extends Fragment implements DialogHelper.OnSavedL
|
|||||||
ReminderHelper.createReminderAlarms(activity);
|
ReminderHelper.createReminderAlarms(activity);
|
||||||
activity.recreate();
|
activity.recreate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHistoryEditorClosed()
|
||||||
|
{
|
||||||
|
refreshData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshData()
|
||||||
|
{
|
||||||
|
streakView.refreshData();
|
||||||
|
historyView.refreshData();
|
||||||
|
scoreView.refreshData();
|
||||||
|
updateScoreRing(getView());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ public class RepetitionList
|
|||||||
|
|
||||||
public void toggle(long timestamp)
|
public void toggle(long timestamp)
|
||||||
{
|
{
|
||||||
|
timestamp = DateHelper.getStartOfDay(timestamp);
|
||||||
|
|
||||||
if (contains(timestamp))
|
if (contains(timestamp))
|
||||||
{
|
{
|
||||||
delete(timestamp);
|
delete(timestamp);
|
||||||
|
|||||||
@@ -126,6 +126,9 @@ public class ScoreList
|
|||||||
|
|
||||||
public int[] getAllValues(Long fromTimestamp, Long toTimestamp, Integer divisor)
|
public int[] getAllValues(Long fromTimestamp, Long toTimestamp, Integer divisor)
|
||||||
{
|
{
|
||||||
|
// Force rebuild of the score table
|
||||||
|
getNewestValue();
|
||||||
|
|
||||||
Long offset = toTimestamp - (divisor - 1) * DateHelper.millisecondsInOneDay;
|
Long offset = toTimestamp - (divisor - 1) * DateHelper.millisecondsInOneDay;
|
||||||
|
|
||||||
String query = "select ((timestamp - ?) / ?) as time, avg(score) from Score " +
|
String query = "select ((timestamp - ?) / ?) as time, avg(score) from Score " +
|
||||||
|
|||||||
@@ -25,10 +25,13 @@ import android.graphics.Color;
|
|||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Paint.Align;
|
import android.graphics.Paint.Align;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
import org.isoron.helpers.ColorHelper;
|
import org.isoron.helpers.ColorHelper;
|
||||||
import org.isoron.helpers.DateHelper;
|
import org.isoron.helpers.DateHelper;
|
||||||
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@@ -50,7 +53,6 @@ public class HabitHistoryView extends ScrollableDataView
|
|||||||
private int columnWidth;
|
private int columnWidth;
|
||||||
private int columnHeight;
|
private int columnHeight;
|
||||||
private int nColumns;
|
private int nColumns;
|
||||||
private int baseSize;
|
|
||||||
|
|
||||||
private String wdays[];
|
private String wdays[];
|
||||||
private SimpleDateFormat dfMonth;
|
private SimpleDateFormat dfMonth;
|
||||||
@@ -65,11 +67,14 @@ public class HabitHistoryView extends ScrollableDataView
|
|||||||
|
|
||||||
private boolean isBackgroundTransparent;
|
private boolean isBackgroundTransparent;
|
||||||
private int textColor;
|
private int textColor;
|
||||||
|
private boolean isEditable;
|
||||||
|
|
||||||
public HabitHistoryView(Context context, AttributeSet attrs)
|
public HabitHistoryView(Context context, AttributeSet attrs)
|
||||||
{
|
{
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
this.primaryColor = ColorHelper.palette[7];
|
this.primaryColor = ColorHelper.palette[7];
|
||||||
|
this.checkmarks = new int[0];
|
||||||
|
this.isEditable = false;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,12 +82,13 @@ public class HabitHistoryView extends ScrollableDataView
|
|||||||
{
|
{
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
createColors();
|
createColors();
|
||||||
fetchData();
|
refreshData();
|
||||||
postInvalidate();
|
postInvalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
|
refreshData();
|
||||||
createPaints();
|
createPaints();
|
||||||
createColors();
|
createColors();
|
||||||
|
|
||||||
@@ -96,6 +102,7 @@ public class HabitHistoryView extends ScrollableDataView
|
|||||||
private void updateDate()
|
private void updateDate()
|
||||||
{
|
{
|
||||||
baseDate = new GregorianCalendar();
|
baseDate = new GregorianCalendar();
|
||||||
|
baseDate.setTimeInMillis(DateHelper.getLocalTime());
|
||||||
baseDate.add(Calendar.DAY_OF_YEAR, -(getDataOffset() - 1) * 7);
|
baseDate.add(Calendar.DAY_OF_YEAR, -(getDataOffset() - 1) * 7);
|
||||||
|
|
||||||
nDays = (nColumns - 1) * 7;
|
nDays = (nColumns - 1) * 7;
|
||||||
@@ -117,23 +124,42 @@ public class HabitHistoryView extends ScrollableDataView
|
|||||||
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
|
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
|
||||||
{
|
{
|
||||||
if(height < 8) height = 200;
|
if(height < 8) height = 200;
|
||||||
|
int baseSize = height / 8;
|
||||||
baseSize = height / 8;
|
|
||||||
setScrollerBucketSize(baseSize);
|
setScrollerBucketSize(baseSize);
|
||||||
|
|
||||||
columnWidth = baseSize;
|
|
||||||
columnHeight = 8 * baseSize;
|
|
||||||
nColumns = width / baseSize;
|
|
||||||
|
|
||||||
squareSpacing = (int) Math.floor(baseSize / 15.0);
|
squareSpacing = (int) Math.floor(baseSize / 15.0);
|
||||||
pSquareFg.setTextSize(baseSize * 0.5f);
|
int maxTextSize = getResources().getDimensionPixelSize(R.dimen.history_max_font_size);
|
||||||
pTextHeader.setTextSize(baseSize * 0.5f);
|
float textSize = Math.min(baseSize * 0.5f, maxTextSize);
|
||||||
|
|
||||||
|
pSquareFg.setTextSize(textSize);
|
||||||
|
pTextHeader.setTextSize(textSize);
|
||||||
squareTextOffset = pSquareFg.getFontSpacing() * 0.4f;
|
squareTextOffset = pSquareFg.getFontSpacing() * 0.4f;
|
||||||
headerTextOffset = pTextHeader.getFontSpacing() * 0.3f;
|
headerTextOffset = pTextHeader.getFontSpacing() * 0.3f;
|
||||||
|
|
||||||
|
int rightLabelWidth = getWeekdayLabelWidth();
|
||||||
|
int horizontalPadding = getPaddingRight() + getPaddingLeft();
|
||||||
|
|
||||||
|
columnWidth = baseSize;
|
||||||
|
columnHeight = 8 * baseSize;
|
||||||
|
nColumns = (width - rightLabelWidth - horizontalPadding) / baseSize + 1;
|
||||||
|
|
||||||
updateDate();
|
updateDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getWeekdayLabelWidth()
|
||||||
|
{
|
||||||
|
int width = 0;
|
||||||
|
Rect bounds = new Rect();
|
||||||
|
|
||||||
|
for(String w : wdays)
|
||||||
|
{
|
||||||
|
pSquareFg.getTextBounds(w, 0, w.length(), bounds);
|
||||||
|
width = Math.max(width, bounds.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
private void createColors()
|
private void createColors()
|
||||||
{
|
{
|
||||||
if(habit != null)
|
if(habit != null)
|
||||||
@@ -179,22 +205,18 @@ public class HabitHistoryView extends ScrollableDataView
|
|||||||
pSquareFg.setTextAlign(Align.CENTER);
|
pSquareFg.setTextAlign(Align.CENTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fetchData()
|
public void refreshData()
|
||||||
{
|
{
|
||||||
if(isInEditMode())
|
if(isInEditMode())
|
||||||
generateRandomData();
|
generateRandomData();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(habit == null)
|
if(habit == null) return;
|
||||||
{
|
|
||||||
checkmarks = new int[0];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkmarks = habit.checkmarks.getAllValues();
|
checkmarks = habit.checkmarks.getAllValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDate();
|
updateDate();
|
||||||
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateRandomData()
|
private void generateRandomData()
|
||||||
@@ -226,6 +248,7 @@ public class HabitHistoryView extends ScrollableDataView
|
|||||||
super.onDraw(canvas);
|
super.onDraw(canvas);
|
||||||
|
|
||||||
baseLocation.set(0, 0, columnWidth - squareSpacing, columnWidth - squareSpacing);
|
baseLocation.set(0, 0, columnWidth - squareSpacing, columnWidth - squareSpacing);
|
||||||
|
baseLocation.offset(getPaddingLeft(), getPaddingTop());
|
||||||
|
|
||||||
previousMonth = "";
|
previousMonth = "";
|
||||||
previousYear = "";
|
previousYear = "";
|
||||||
@@ -329,4 +352,59 @@ public class HabitHistoryView extends ScrollableDataView
|
|||||||
this.isBackgroundTransparent = isBackgroundTransparent;
|
this.isBackgroundTransparent = isBackgroundTransparent;
|
||||||
createColors();
|
createColors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onSingleTapUp(MotionEvent e)
|
||||||
|
{
|
||||||
|
if(!isEditable) return false;
|
||||||
|
|
||||||
|
int pointerId = e.getPointerId(0);
|
||||||
|
float x = e.getX(pointerId);
|
||||||
|
float y = e.getY(pointerId);
|
||||||
|
|
||||||
|
final Long timestamp = positionToTimestamp(x, y);
|
||||||
|
if(timestamp == null) return false;
|
||||||
|
|
||||||
|
new AsyncTask<Void, Void, Void>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params)
|
||||||
|
{
|
||||||
|
habit.repetitions.toggle(timestamp);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void aVoid)
|
||||||
|
{
|
||||||
|
refreshData();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
|
||||||
|
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(DateHelper.getStartOfDay(date.getTimeInMillis()) > DateHelper.getStartOfToday())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return date.getTimeInMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsEditable(boolean isEditable)
|
||||||
|
{
|
||||||
|
this.isEditable = isEditable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ public class HabitScoreView extends ScrollableDataView
|
|||||||
{
|
{
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
this.primaryColor = ColorHelper.palette[7];
|
this.primaryColor = ColorHelper.palette[7];
|
||||||
|
this.scores = new int[0];
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,12 +79,13 @@ public class HabitScoreView extends ScrollableDataView
|
|||||||
{
|
{
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
createColors();
|
createColors();
|
||||||
fetchData();
|
refreshData();
|
||||||
postInvalidate();
|
postInvalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
|
refreshData();
|
||||||
createPaints();
|
createPaints();
|
||||||
createColors();
|
createColors();
|
||||||
|
|
||||||
@@ -162,21 +164,17 @@ public class HabitScoreView extends ScrollableDataView
|
|||||||
em = pText.getFontSpacing();
|
em = pText.getFontSpacing();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fetchData()
|
public void refreshData()
|
||||||
{
|
{
|
||||||
if(isInEditMode())
|
if(isInEditMode())
|
||||||
generateRandomData();
|
generateRandomData();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (habit == null)
|
if (habit == null) return;
|
||||||
{
|
|
||||||
scores = new int[0];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
scores = habit.scores.getAllValues(BUCKET_SIZE * DateHelper.millisecondsInOneDay);
|
scores = habit.scores.getAllValues(BUCKET_SIZE * DateHelper.millisecondsInOneDay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateRandomData()
|
private void generateRandomData()
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ public class HabitStreakView extends ScrollableDataView
|
|||||||
{
|
{
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
this.primaryColor = ColorHelper.palette[7];
|
this.primaryColor = ColorHelper.palette[7];
|
||||||
|
startTimes = endTimes = lengths = new long[0];
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,12 +74,13 @@ public class HabitStreakView extends ScrollableDataView
|
|||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
|
|
||||||
createColors();
|
createColors();
|
||||||
fetchData();
|
refreshData();
|
||||||
postInvalidate();
|
postInvalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
|
refreshData();
|
||||||
createPaints();
|
createPaints();
|
||||||
createColors();
|
createColors();
|
||||||
|
|
||||||
@@ -157,17 +159,13 @@ public class HabitStreakView extends ScrollableDataView
|
|||||||
pBar.setAntiAlias(true);
|
pBar.setAntiAlias(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fetchData()
|
public void refreshData()
|
||||||
{
|
{
|
||||||
if(isInEditMode())
|
if(isInEditMode())
|
||||||
generateRandomData();
|
generateRandomData();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(habit == null)
|
if(habit == null) return;
|
||||||
{
|
|
||||||
startTimes = endTimes = lengths = new long[0];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Streak> streaks = habit.streaks.getAll();
|
List<Streak> streaks = habit.streaks.getAll();
|
||||||
int size = streaks.size();
|
int size = streaks.size();
|
||||||
@@ -187,6 +185,8 @@ public class HabitStreakView extends ScrollableDataView
|
|||||||
maxStreakLength = Math.max(maxStreakLength, s.length);
|
maxStreakLength = Math.max(maxStreakLength, s.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateRandomData()
|
private void generateRandomData()
|
||||||
|
|||||||
@@ -58,8 +58,6 @@ public abstract class ScrollableDataView extends View implements GestureDetector
|
|||||||
scrollAnimator.addUpdateListener(this);
|
scrollAnimator.addUpdateListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void fetchData();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent event)
|
public boolean onTouchEvent(MotionEvent event)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
xmlns:app="http://isoron.org/android"
|
xmlns:app="http://isoron.org/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/windowBackground"
|
android:background="@color/windowBackground"
|
||||||
@@ -60,24 +60,32 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout style="@style/cardStyle">
|
<LinearLayout
|
||||||
|
style="@style/cardStyle"
|
||||||
|
android:paddingBottom="0dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvHistory"
|
android:id="@+id/tvHistory"
|
||||||
style="@style/cardHeaderStyle"
|
style="@style/cardHeaderStyle"
|
||||||
android:text="@string/history"/>
|
android:text="@string/history"/>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/llHistory"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"/>
|
|
||||||
|
|
||||||
<org.isoron.uhabits.views.HabitHistoryView
|
<org.isoron.uhabits.views.HabitHistoryView
|
||||||
android:id="@+id/historyView"
|
android:id="@+id/historyView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="160dp" />
|
android:layout_height="160dp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:id="@+id/btEditHistory"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:src="@drawable/ic_action_edit_light"
|
||||||
|
android:textColor="@color/grey_400"
|
||||||
|
android:text="@string/edit"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout style="@style/cardStyle">
|
<LinearLayout style="@style/cardStyle">
|
||||||
|
|||||||
@@ -316,7 +316,7 @@
|
|||||||
<color name="grey_100">#F5F5F5</color>
|
<color name="grey_100">#F5F5F5</color>
|
||||||
<!--<color name="grey_200">#EEEEEE</color>-->
|
<!--<color name="grey_200">#EEEEEE</color>-->
|
||||||
<!--<color name="grey_300">#E0E0E0</color>-->
|
<!--<color name="grey_300">#E0E0E0</color>-->
|
||||||
<!--<color name="grey_400">#BDBDBD</color>-->
|
<color name="grey_400">#BDBDBD</color>
|
||||||
<color name="grey_500">#9E9E9E</color>
|
<color name="grey_500">#9E9E9E</color>
|
||||||
<!--<color name="grey_600">#757575</color>-->
|
<!--<color name="grey_600">#757575</color>-->
|
||||||
<!--<color name="grey_700">#616161</color>-->
|
<!--<color name="grey_700">#616161</color>-->
|
||||||
|
|||||||
@@ -20,6 +20,9 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<dimen name="small_square_size">20dp</dimen>
|
<dimen name="small_square_size">20dp</dimen>
|
||||||
<dimen name="check_square_size">42dp</dimen>
|
<dimen name="check_square_size">42dp</dimen>
|
||||||
|
<dimen name="history_editor_max_height">450dp</dimen>
|
||||||
|
<dimen name="history_editor_padding">8dp</dimen>
|
||||||
|
<dimen name="history_max_font_size">14sp</dimen>
|
||||||
|
|
||||||
<string-array name="snooze_interval_names">
|
<string-array name="snooze_interval_names">
|
||||||
<item>@string/interval_15_minutes</item>
|
<item>@string/interval_15_minutes</item>
|
||||||
|
|||||||
Reference in New Issue
Block a user