Improve view tests
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 34 KiB |
@@ -29,15 +29,14 @@ import org.isoron.uhabits.utils.*;
|
|||||||
import org.isoron.uhabits.widgets.*;
|
import org.isoron.uhabits.widgets.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
import static android.view.View.MeasureSpec.*;
|
import static android.view.View.MeasureSpec.*;
|
||||||
import static junit.framework.Assert.*;
|
import static junit.framework.Assert.*;
|
||||||
|
|
||||||
public class BaseViewTest extends BaseAndroidTest
|
public class BaseViewTest extends BaseAndroidTest
|
||||||
{
|
{
|
||||||
protected static final double DEFAULT_SIMILARITY_CUTOFF = 0.09;
|
protected static final double DEFAULT_SIMILARITY_CUTOFF = 0.001;
|
||||||
|
|
||||||
public static final int HISTOGRAM_BIN_SIZE = 8;
|
|
||||||
|
|
||||||
private double similarityCutoff;
|
private double similarityCutoff;
|
||||||
|
|
||||||
@@ -67,11 +66,10 @@ public class BaseViewTest extends BaseAndroidTest
|
|||||||
Bitmap scaledExpected =
|
Bitmap scaledExpected =
|
||||||
Bitmap.createScaledBitmap(expected, width, height, true);
|
Bitmap.createScaledBitmap(expected, width, height, true);
|
||||||
|
|
||||||
double distance;
|
|
||||||
boolean similarEnough = true;
|
boolean similarEnough = true;
|
||||||
|
double distance = distance(actual, scaledExpected);
|
||||||
|
|
||||||
if ((distance = compareHistograms(getHistogram(actual),
|
if (distance > similarityCutoff)
|
||||||
getHistogram(scaledExpected))) > similarityCutoff)
|
|
||||||
{
|
{
|
||||||
similarEnough = false;
|
similarEnough = false;
|
||||||
errorMessage.append(String.format(
|
errorMessage.append(String.format(
|
||||||
@@ -144,58 +142,47 @@ public class BaseViewTest extends BaseAndroidTest
|
|||||||
e.recycle();
|
e.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
private double compareHistograms(int[][] actualHistogram,
|
|
||||||
int[][] expectedHistogram)
|
|
||||||
{
|
|
||||||
long diff = 0;
|
|
||||||
long total = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < 256 / HISTOGRAM_BIN_SIZE; i++)
|
|
||||||
{
|
|
||||||
diff += Math.abs(actualHistogram[0][i] - expectedHistogram[0][i]);
|
|
||||||
diff += Math.abs(actualHistogram[1][i] - expectedHistogram[1][i]);
|
|
||||||
diff += Math.abs(actualHistogram[2][i] - expectedHistogram[2][i]);
|
|
||||||
diff += Math.abs(actualHistogram[3][i] - expectedHistogram[3][i]);
|
|
||||||
|
|
||||||
total += actualHistogram[0][i];
|
|
||||||
total += actualHistogram[1][i];
|
|
||||||
total += actualHistogram[2][i];
|
|
||||||
total += actualHistogram[3][i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return (double) diff / total / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Bitmap getBitmapFromAssets(String path) throws IOException
|
private Bitmap getBitmapFromAssets(String path) throws IOException
|
||||||
{
|
{
|
||||||
InputStream stream = testContext.getAssets().open(path);
|
InputStream stream = testContext.getAssets().open(path);
|
||||||
return BitmapFactory.decodeStream(stream);
|
return BitmapFactory.decodeStream(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int[][] getHistogram(Bitmap bitmap)
|
private double distance(Bitmap b1, Bitmap b2)
|
||||||
{
|
{
|
||||||
int histogram[][] = new int[4][256 / HISTOGRAM_BIN_SIZE];
|
if(b1.getWidth() != b2.getWidth()) return 1.0;
|
||||||
|
if(b1.getHeight() != b2.getHeight()) return 1.0;
|
||||||
|
|
||||||
for (int x = 0; x < bitmap.getWidth(); x++)
|
Random random = new Random();
|
||||||
|
|
||||||
|
double distance = 0.0;
|
||||||
|
for (int x = 0; x < b1.getWidth(); x++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < bitmap.getHeight(); y++)
|
for (int y = 0; y < b1.getHeight(); y++)
|
||||||
{
|
{
|
||||||
int color = bitmap.getPixel(x, y);
|
if(random.nextInt(4) != 0) continue;
|
||||||
int[] argb = new int[]{
|
|
||||||
(color >> 24) & 0xff, //alpha
|
int[] argb1 = colorToArgb(b1.getPixel(x, y));
|
||||||
(color >> 16) & 0xff, //red
|
int[] argb2 = colorToArgb(b2.getPixel(x, y));
|
||||||
(color >> 8) & 0xff, //green
|
distance += Math.abs(argb1[0] - argb2[0]);
|
||||||
(color) & 0xff //blue
|
distance += Math.abs(argb1[1] - argb2[1]);
|
||||||
|
distance += Math.abs(argb1[2] - argb2[2]);
|
||||||
|
distance += Math.abs(argb1[3] - argb2[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
distance /= (0xff * 16) * b1.getWidth() * b1.getHeight();
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int[] colorToArgb(int c1)
|
||||||
|
{
|
||||||
|
return new int[]{
|
||||||
|
(c1 >> 24) & 0xff, //alpha
|
||||||
|
(c1 >> 16) & 0xff, //red
|
||||||
|
(c1 >> 8) & 0xff, //green
|
||||||
|
(c1) & 0xff //blue
|
||||||
};
|
};
|
||||||
|
|
||||||
histogram[0][argb[0] / HISTOGRAM_BIN_SIZE]++;
|
|
||||||
histogram[1][argb[1] / HISTOGRAM_BIN_SIZE]++;
|
|
||||||
histogram[2][argb[2] / HISTOGRAM_BIN_SIZE]++;
|
|
||||||
histogram[3][argb[3] / HISTOGRAM_BIN_SIZE]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return histogram;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getVersionedViewAssetPath(String path)
|
private String getVersionedViewAssetPath(String path)
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ public class HabitCardViewTest extends BaseViewTest
|
|||||||
view.setSelected(false);
|
view.setSelected(false);
|
||||||
view.setScore(habit.getScores().getTodayValue());
|
view.setScore(habit.getScores().getTodayValue());
|
||||||
view.setController(controller);
|
view.setController(controller);
|
||||||
|
view.setButtonCount(6);
|
||||||
measureView(view, dpToPixels(400), dpToPixels(50));
|
measureView(view, dpToPixels(400), dpToPixels(50));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +87,7 @@ public class HabitCardViewTest extends BaseViewTest
|
|||||||
habit.setName("Wake up early");
|
habit.setName("Wake up early");
|
||||||
habit.setColor(2);
|
habit.setColor(2);
|
||||||
habit.getObservable().notifyListeners();
|
habit.getObservable().notifyListeners();
|
||||||
|
Thread.sleep(500);
|
||||||
assertRenders(view, PATH + "render_changed.png");
|
assertRenders(view, PATH + "render_changed.png");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* 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.activities.habits.list.views;
|
||||||
|
|
||||||
|
import android.support.test.filters.*;
|
||||||
|
import android.support.test.runner.*;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.*;
|
||||||
|
import org.isoron.uhabits.preferences.*;
|
||||||
|
import org.isoron.uhabits.utils.*;
|
||||||
|
import org.junit.*;
|
||||||
|
import org.junit.runner.*;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@MediumTest
|
||||||
|
public class HeaderViewTest extends BaseViewTest
|
||||||
|
{
|
||||||
|
public static final String PATH = "habits/list/HeaderView/";
|
||||||
|
|
||||||
|
private HeaderView view;
|
||||||
|
|
||||||
|
private Preferences prefs;
|
||||||
|
|
||||||
|
private MidnightTimer midnightTimer;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Before
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
super.setUp();
|
||||||
|
setSimilarityCutoff(0);
|
||||||
|
|
||||||
|
prefs = mock(Preferences.class);
|
||||||
|
midnightTimer = mock(MidnightTimer.class);
|
||||||
|
view = new HeaderView(targetContext, prefs, midnightTimer);
|
||||||
|
view.setButtonCount(5);
|
||||||
|
measureView(view, dpToPixels(600), dpToPixels(48));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRender() throws Exception
|
||||||
|
{
|
||||||
|
when(prefs.shouldReverseCheckmarks()).thenReturn(false);
|
||||||
|
|
||||||
|
assertRenders(view, PATH + "render.png");
|
||||||
|
|
||||||
|
verify(prefs).shouldReverseCheckmarks();
|
||||||
|
verifyNoMoreInteractions(prefs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRender_reverse() throws Exception
|
||||||
|
{
|
||||||
|
when(prefs.shouldReverseCheckmarks()).thenReturn(true);
|
||||||
|
|
||||||
|
assertRenders(view, PATH + "render_reverse.png");
|
||||||
|
|
||||||
|
verify(prefs).shouldReverseCheckmarks();
|
||||||
|
verifyNoMoreInteractions(prefs);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* 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.activities.habits.list.views;
|
||||||
|
|
||||||
|
import android.support.test.filters.*;
|
||||||
|
import android.support.test.runner.*;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.*;
|
||||||
|
import org.isoron.uhabits.activities.habits.list.controllers.*;
|
||||||
|
import org.isoron.uhabits.utils.*;
|
||||||
|
import org.junit.*;
|
||||||
|
import org.junit.runner.*;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@MediumTest
|
||||||
|
public class NumberButtonViewTest extends BaseViewTest
|
||||||
|
{
|
||||||
|
public static final String PATH = "habits/list/NumberButtonView/";
|
||||||
|
|
||||||
|
private NumberButtonView view;
|
||||||
|
|
||||||
|
private NumberButtonController controller;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Before
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
super.setUp();
|
||||||
|
setSimilarityCutoff(0.015f);
|
||||||
|
|
||||||
|
view = new NumberButtonView(targetContext);
|
||||||
|
|
||||||
|
view.setUnit("steps");
|
||||||
|
view.setThreshold(100.0);
|
||||||
|
view.setColor(ColorUtils.getAndroidTestColor(5));
|
||||||
|
|
||||||
|
measureView(view, dpToPixels(48), dpToPixels(48));
|
||||||
|
|
||||||
|
controller = mock(NumberButtonController.class);
|
||||||
|
view.setController(controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFormatValue()
|
||||||
|
{
|
||||||
|
assertThat(NumberButtonView.formatValue(0.1235), equalTo("0.12"));
|
||||||
|
assertThat(NumberButtonView.formatValue(0.1000), equalTo("0.1"));
|
||||||
|
assertThat(NumberButtonView.formatValue(5.0), equalTo("5"));
|
||||||
|
assertThat(NumberButtonView.formatValue(5.25), equalTo("5.25"));
|
||||||
|
assertThat(NumberButtonView.formatValue(12.3456), equalTo("12.3"));
|
||||||
|
assertThat(NumberButtonView.formatValue(123.123), equalTo("123"));
|
||||||
|
assertThat(NumberButtonView.formatValue(321.2), equalTo("321"));
|
||||||
|
assertThat(NumberButtonView.formatValue(4321.2), equalTo("4.3k"));
|
||||||
|
assertThat(NumberButtonView.formatValue(54321.2), equalTo("54.3k"));
|
||||||
|
assertThat(NumberButtonView.formatValue(654321.2), equalTo("654k"));
|
||||||
|
assertThat(NumberButtonView.formatValue(7654321.2), equalTo("7.7M"));
|
||||||
|
assertThat(NumberButtonView.formatValue(87654321.2), equalTo("87.7M"));
|
||||||
|
assertThat(NumberButtonView.formatValue(987654321.2), equalTo("988M"));
|
||||||
|
assertThat(NumberButtonView.formatValue(1987654321.2), equalTo("2.0G"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRender_aboveThreshold() throws Exception
|
||||||
|
{
|
||||||
|
view.setValue(500);
|
||||||
|
assertRenders(view, PATH + "render_above.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRender_belowThreshold() throws Exception
|
||||||
|
{
|
||||||
|
view.setValue(99);
|
||||||
|
assertRenders(view, PATH + "render_below.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRender_zero() throws Exception
|
||||||
|
{
|
||||||
|
view.setValue(0);
|
||||||
|
assertRenders(view, PATH + "render_zero.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_click()
|
||||||
|
{
|
||||||
|
view.performClick();
|
||||||
|
verify(controller).onClick();
|
||||||
|
|
||||||
|
view.performLongClick();
|
||||||
|
verify(controller).onLongClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,7 +25,6 @@ import android.widget.*;
|
|||||||
|
|
||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.models.*;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.widgets.*;
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
import org.junit.runner.*;
|
import org.junit.runner.*;
|
||||||
|
|
||||||
@@ -37,7 +36,7 @@ import static org.isoron.uhabits.models.Checkmark.*;
|
|||||||
@MediumTest
|
@MediumTest
|
||||||
public class CheckmarkWidgetTest extends BaseViewTest
|
public class CheckmarkWidgetTest extends BaseViewTest
|
||||||
{
|
{
|
||||||
private static final String PATH = "widgets/CheckmarkWidgetView/";
|
private static final String PATH = "widgets/CheckmarkWidget/";
|
||||||
|
|
||||||
private Habit habit;
|
private Habit habit;
|
||||||
|
|
||||||
@@ -49,6 +48,8 @@ public class CheckmarkWidgetTest extends BaseViewTest
|
|||||||
public void setUp()
|
public void setUp()
|
||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
setTheme(R.style.TransparentWidgetTheme);
|
||||||
|
|
||||||
habit = fixtures.createShortHabit();
|
habit = fixtures.createShortHabit();
|
||||||
checkmarks = habit.getCheckmarks();
|
checkmarks = habit.getCheckmarks();
|
||||||
CheckmarkWidget widget = new CheckmarkWidget(targetContext, 0, habit);
|
CheckmarkWidget widget = new CheckmarkWidget(targetContext, 0, habit);
|
||||||
@@ -80,6 +81,6 @@ public class CheckmarkWidgetTest extends BaseViewTest
|
|||||||
@Test
|
@Test
|
||||||
public void testRender() throws Exception
|
public void testRender() throws Exception
|
||||||
{
|
{
|
||||||
assertRenders(view, PATH + "checked.png");
|
assertRenders(view, PATH + "render.png");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,8 +38,6 @@ public class CheckmarkWidgetViewTest extends BaseViewTest
|
|||||||
|
|
||||||
private CheckmarkWidgetView view;
|
private CheckmarkWidgetView view;
|
||||||
|
|
||||||
private Habit habit;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Before
|
@Before
|
||||||
public void setUp()
|
public void setUp()
|
||||||
@@ -47,13 +45,12 @@ public class CheckmarkWidgetViewTest extends BaseViewTest
|
|||||||
super.setUp();
|
super.setUp();
|
||||||
setTheme(R.style.TransparentWidgetTheme);
|
setTheme(R.style.TransparentWidgetTheme);
|
||||||
|
|
||||||
habit = fixtures.createShortHabit();
|
Habit habit = fixtures.createShortHabit();
|
||||||
view = new CheckmarkWidgetView(targetContext);
|
view = new CheckmarkWidgetView(targetContext);
|
||||||
int color = ColorUtils.getAndroidTestColor(habit.getColor());
|
|
||||||
double score = habit.getScores().getTodayValue();
|
double score = habit.getScores().getTodayValue();
|
||||||
float percentage = (float) score;
|
float percentage = (float) score;
|
||||||
|
|
||||||
view.setActiveColor(color);
|
view.setActiveColor(ColorUtils.getAndroidTestColor(0));
|
||||||
view.setCheckmarkValue(habit.getCheckmarks().getTodayValue());
|
view.setCheckmarkValue(habit.getCheckmarks().getTodayValue());
|
||||||
view.setPercentage(percentage);
|
view.setPercentage(percentage);
|
||||||
view.setName(habit.getName());
|
view.setName(habit.getName());
|
||||||
|
|||||||
@@ -116,14 +116,14 @@ public class HabitCardView extends FrameLayout
|
|||||||
|
|
||||||
public void setHabit(@NonNull Habit habit)
|
public void setHabit(@NonNull Habit habit)
|
||||||
{
|
{
|
||||||
if (this.habit != null) detachFromHabit();
|
if (isAttachedToWindow()) stopListening();
|
||||||
|
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
checkmarkPanel.setHabit(habit);
|
checkmarkPanel.setHabit(habit);
|
||||||
numberPanel.setHabit(habit);
|
numberPanel.setHabit(habit);
|
||||||
refresh();
|
|
||||||
|
|
||||||
attachToHabit();
|
refresh();
|
||||||
|
if (isAttachedToWindow()) startListening();
|
||||||
postInvalidate();
|
postInvalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,23 +176,20 @@ public class HabitCardView extends FrameLayout
|
|||||||
triggerRipple(x, y);
|
triggerRipple(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onAttachedToWindow()
|
||||||
|
{
|
||||||
|
super.onAttachedToWindow();
|
||||||
|
stopListening();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDetachedFromWindow()
|
protected void onDetachedFromWindow()
|
||||||
{
|
{
|
||||||
if (habit != null) detachFromHabit();
|
startListening();
|
||||||
super.onDetachedFromWindow();
|
super.onDetachedFromWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void attachToHabit()
|
|
||||||
{
|
|
||||||
if (habit != null) habit.getObservable().addListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void detachFromHabit()
|
|
||||||
{
|
|
||||||
if (habit != null) habit.getObservable().removeListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getActiveColor(Habit habit)
|
private int getActiveColor(Habit habit)
|
||||||
{
|
{
|
||||||
int mediumContrastColor = res.getColor(R.attr.mediumContrastTextColor);
|
int mediumContrastColor = res.getColor(R.attr.mediumContrastTextColor);
|
||||||
@@ -309,6 +306,16 @@ public class HabitCardView extends FrameLayout
|
|||||||
postInvalidate();
|
postInvalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startListening()
|
||||||
|
{
|
||||||
|
if (habit != null) habit.getObservable().removeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopListening()
|
||||||
|
{
|
||||||
|
if (habit != null) habit.getObservable().addListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
private void triggerRipple(final float x, final float y)
|
private void triggerRipple(final float x, final float y)
|
||||||
{
|
{
|
||||||
final Drawable background = innerFrame.getBackground();
|
final Drawable background = innerFrame.getBackground();
|
||||||
|
|||||||
@@ -46,19 +46,24 @@ public class HeaderView extends ScrollableChart
|
|||||||
@Nullable
|
@Nullable
|
||||||
private MidnightTimer midnightTimer;
|
private MidnightTimer midnightTimer;
|
||||||
|
|
||||||
private final TextPaint paint;
|
private TextPaint paint;
|
||||||
|
|
||||||
private RectF rect;
|
private RectF rect;
|
||||||
|
|
||||||
public HeaderView(Context context, AttributeSet attrs)
|
public HeaderView(@NonNull Context context,
|
||||||
|
@NonNull Preferences prefs,
|
||||||
|
@NonNull MidnightTimer midnightTimer)
|
||||||
|
{
|
||||||
|
super(context);
|
||||||
|
this.prefs = prefs;
|
||||||
|
this.midnightTimer = midnightTimer;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public HeaderView(Context context, @Nullable AttributeSet attrs)
|
||||||
{
|
{
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
|
|
||||||
if (isInEditMode())
|
|
||||||
{
|
|
||||||
setButtonCount(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
Context appContext = context.getApplicationContext();
|
Context appContext = context.getApplicationContext();
|
||||||
if (appContext instanceof HabitsApplication)
|
if (appContext instanceof HabitsApplication)
|
||||||
{
|
{
|
||||||
@@ -68,23 +73,12 @@ public class HeaderView extends ScrollableChart
|
|||||||
|
|
||||||
if (context instanceof ListHabitsActivity)
|
if (context instanceof ListHabitsActivity)
|
||||||
{
|
{
|
||||||
ListHabitsActivity activity = (ListHabitsActivity) context;
|
ListHabitsComponent component =
|
||||||
midnightTimer = activity.getListHabitsComponent().getMidnightTimer();
|
((ListHabitsActivity) context).getListHabitsComponent();
|
||||||
|
midnightTimer = component.getMidnightTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
Resources res = context.getResources();
|
init();
|
||||||
setScrollerBucketSize((int) res.getDimension(R.dimen.checkmarkWidth));
|
|
||||||
|
|
||||||
StyledResources sr = new StyledResources(context);
|
|
||||||
paint = new TextPaint();
|
|
||||||
paint.setColor(Color.BLACK);
|
|
||||||
paint.setAntiAlias(true);
|
|
||||||
paint.setTextSize(getResources().getDimension(R.dimen.tinyTextSize));
|
|
||||||
paint.setTextAlign(Paint.Align.CENTER);
|
|
||||||
paint.setTypeface(Typeface.DEFAULT_BOLD);
|
|
||||||
paint.setColor(sr.getColor(R.attr.mediumContrastTextColor));
|
|
||||||
|
|
||||||
rect = new RectF();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -115,14 +109,6 @@ public class HeaderView extends ScrollableChart
|
|||||||
if (midnightTimer != null) midnightTimer.addListener(this);
|
if (midnightTimer != null) midnightTimer.addListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateDirection()
|
|
||||||
{
|
|
||||||
int direction = -1;
|
|
||||||
if (shouldReverseCheckmarks()) direction *= -1;
|
|
||||||
if (InterfaceUtils.isLayoutRtl(this)) direction *= -1;
|
|
||||||
setDirection(direction);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDetachedFromWindow()
|
protected void onDetachedFromWindow()
|
||||||
{
|
{
|
||||||
@@ -131,16 +117,6 @@ public class HeaderView extends ScrollableChart
|
|||||||
super.onDetachedFromWindow();
|
super.onDetachedFromWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
|
||||||
{
|
|
||||||
int width = MeasureSpec.getSize(widthMeasureSpec);
|
|
||||||
int height = (int) getContext()
|
|
||||||
.getResources()
|
|
||||||
.getDimension(R.dimen.checkmarkHeight);
|
|
||||||
setMeasuredDimension(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas)
|
protected void onDraw(Canvas canvas)
|
||||||
{
|
{
|
||||||
@@ -179,9 +155,46 @@ public class HeaderView extends ScrollableChart
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||||
|
{
|
||||||
|
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
int height = (int) getContext()
|
||||||
|
.getResources()
|
||||||
|
.getDimension(R.dimen.checkmarkHeight);
|
||||||
|
setMeasuredDimension(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init()
|
||||||
|
{
|
||||||
|
Resources res = getContext().getResources();
|
||||||
|
setScrollerBucketSize((int) res.getDimension(R.dimen.checkmarkWidth));
|
||||||
|
|
||||||
|
StyledResources sr = new StyledResources(getContext());
|
||||||
|
paint = new TextPaint();
|
||||||
|
paint.setColor(Color.BLACK);
|
||||||
|
paint.setAntiAlias(true);
|
||||||
|
paint.setTextSize(getResources().getDimension(R.dimen.tinyTextSize));
|
||||||
|
paint.setTextAlign(Paint.Align.CENTER);
|
||||||
|
paint.setTypeface(Typeface.DEFAULT_BOLD);
|
||||||
|
paint.setColor(sr.getColor(R.attr.mediumContrastTextColor));
|
||||||
|
|
||||||
|
rect = new RectF();
|
||||||
|
|
||||||
|
if (isInEditMode()) setButtonCount(5);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean shouldReverseCheckmarks()
|
private boolean shouldReverseCheckmarks()
|
||||||
{
|
{
|
||||||
if (prefs == null) return false;
|
if (prefs == null) return false;
|
||||||
return prefs.shouldReverseCheckmarks();
|
return prefs.shouldReverseCheckmarks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateDirection()
|
||||||
|
{
|
||||||
|
int direction = -1;
|
||||||
|
if (shouldReverseCheckmarks()) direction *= -1;
|
||||||
|
if (InterfaceUtils.isLayoutRtl(this)) direction *= -1;
|
||||||
|
setDirection(direction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import org.isoron.uhabits.*;
|
|||||||
import org.isoron.uhabits.activities.habits.list.controllers.*;
|
import org.isoron.uhabits.activities.habits.list.controllers.*;
|
||||||
import org.isoron.uhabits.utils.*;
|
import org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
import java.text.*;
|
||||||
|
|
||||||
import static org.isoron.uhabits.utils.AttributeSetUtils.*;
|
import static org.isoron.uhabits.utils.AttributeSetUtils.*;
|
||||||
import static org.isoron.uhabits.utils.ColorUtils.*;
|
import static org.isoron.uhabits.utils.ColorUtils.*;
|
||||||
@@ -91,7 +91,6 @@ public class NumberButtonView extends View
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param v
|
* @param v
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -104,6 +103,7 @@ public class NumberButtonView extends View
|
|||||||
if (v >= 1e5) return String.format("%.0fk", v / 1e3);
|
if (v >= 1e5) return String.format("%.0fk", v / 1e3);
|
||||||
if (v >= 1e4) return String.format("%.1fk", v / 1e3);
|
if (v >= 1e4) return String.format("%.1fk", v / 1e3);
|
||||||
if (v >= 1e3) return String.format("%.1fk", v / 1e3);
|
if (v >= 1e3) return String.format("%.1fk", v / 1e3);
|
||||||
|
if (v >= 1e2) return new DecimalFormat("#").format(v);
|
||||||
if (v >= 1e1) return new DecimalFormat("#.#").format(v);
|
if (v >= 1e1) return new DecimalFormat("#.#").format(v);
|
||||||
return new DecimalFormat("#.##").format(v);
|
return new DecimalFormat("#.##").format(v);
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,11 @@ public class NumberButtonView extends View
|
|||||||
public void setController(final NumberButtonController controller)
|
public void setController(final NumberButtonController controller)
|
||||||
{
|
{
|
||||||
setOnClickListener(v -> controller.onClick());
|
setOnClickListener(v -> controller.onClick());
|
||||||
setOnLongClickListener(v -> controller.onLongClick());
|
setOnLongClickListener(v ->
|
||||||
|
{
|
||||||
|
controller.onLongClick();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setThreshold(double threshold)
|
public void setThreshold(double threshold)
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ mkdir -p ${OUTPUT_DIR}/failed
|
|||||||
adb pull /mnt/sdcard/test-screenshots/ ${OUTPUT_DIR}/failed >> $LOG 2>> $LOG
|
adb pull /mnt/sdcard/test-screenshots/ ${OUTPUT_DIR}/failed >> $LOG 2>> $LOG
|
||||||
adb pull /storage/sdcard/test-screenshots/ ${OUTPUT_DIR}/failed >> $LOG 2>> $LOG
|
adb pull /storage/sdcard/test-screenshots/ ${OUTPUT_DIR}/failed >> $LOG 2>> $LOG
|
||||||
adb pull /sdcard/Android/data/${PACKAGE_NAME}/files/test-screenshots/ ${OUTPUT_DIR}/failed >> $LOG 2>> $LOG
|
adb pull /sdcard/Android/data/${PACKAGE_NAME}/files/test-screenshots/ ${OUTPUT_DIR}/failed >> $LOG 2>> $LOG
|
||||||
|
|
||||||
|
adb shell rm -r /mnt/sdcard/test-screenshots/ >> $LOG 2>> $LOG
|
||||||
|
adb shell rm -r /storage/sdcard/test-screenshots/ >> $LOG 2>> $LOG
|
||||||
adb shell rm -r /sdcard/Android/data/${PACKAGE_NAME}/files/test-screenshots/ >> $LOG 2>> $LOG
|
adb shell rm -r /sdcard/Android/data/${PACKAGE_NAME}/files/test-screenshots/ >> $LOG 2>> $LOG
|
||||||
|
|
||||||
info "Fetching logcat..."
|
info "Fetching logcat..."
|
||||||
|
|||||||