From 39e7da81bcbdf4e7f59825844c66eea5c9bfff16 Mon Sep 17 00:00:00 2001 From: Name Date: Fri, 20 Oct 2017 20:11:31 +0300 Subject: [PATCH] implemented custom weekday feature in frequency and history charts --- .../common/views/FrequencyChart.java | 100 ++++----- .../activities/common/views/HistoryChart.java | 177 ++++++---------- .../uhabits/core/preferences/Preferences.java | 193 +++++++----------- .../isoron/uhabits/core/utils/DateUtils.java | 91 +++------ 4 files changed, 212 insertions(+), 349 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/FrequencyChart.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/FrequencyChart.java index 0b47cc000..1c7c02990 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/FrequencyChart.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/FrequencyChart.java @@ -27,14 +27,14 @@ import android.util.*; import org.isoron.androidbase.utils.*; import org.isoron.uhabits.*; import org.isoron.uhabits.core.models.*; +import org.isoron.uhabits.core.preferences.Preferences; import org.isoron.uhabits.core.utils.*; import org.isoron.uhabits.utils.*; import java.text.*; import java.util.*; -public class FrequencyChart extends ScrollableChart -{ +public class FrequencyChart extends ScrollableChart { private Paint pGrid; private float em; @@ -67,39 +67,36 @@ public class FrequencyChart extends ScrollableChart private boolean isBackgroundTransparent; + private int firstWeekDay; + @NonNull private HashMap frequency; private int maxFreq; - public FrequencyChart(Context context) - { + public FrequencyChart(Context context) { super(context); init(); } - public FrequencyChart(Context context, AttributeSet attrs) - { + public FrequencyChart(Context context, AttributeSet attrs) { super(context, attrs); this.frequency = new HashMap<>(); init(); } - public void setColor(int color) - { + public void setColor(int color) { this.primaryColor = color; initColors(); postInvalidate(); } - public void setFrequency(HashMap frequency) - { + public void setFrequency(HashMap frequency) { this.frequency = frequency; maxFreq = getMaxFreq(frequency); postInvalidate(); } - private int getMaxFreq(HashMap frequency) - { + private int getMaxFreq(HashMap frequency) { int maxValue = 1; for (Integer[] values : frequency.values()) @@ -109,14 +106,12 @@ public class FrequencyChart extends ScrollableChart return maxValue; } - public void setIsBackgroundTransparent(boolean isBackgroundTransparent) - { + public void setIsBackgroundTransparent(boolean isBackgroundTransparent) { this.isBackgroundTransparent = isBackgroundTransparent; initColors(); } - protected void initPaints() - { + protected void initPaints() { pText = new Paint(); pText.setAntiAlias(true); @@ -129,8 +124,7 @@ public class FrequencyChart extends ScrollableChart } @Override - protected void onDraw(Canvas canvas) - { + protected void onDraw(Canvas canvas) { super.onDraw(canvas); rect.set(0, 0, nColumns * columnWidth, columnHeight); @@ -148,8 +142,7 @@ public class FrequencyChart extends ScrollableChart currentDate.set(Calendar.DAY_OF_MONTH, 1); currentDate.add(Calendar.MONTH, -nColumns + 2 - getDataOffset()); - for (int i = 0; i < nColumns - 1; i++) - { + for (int i = 0; i < nColumns - 1; i++) { rect.set(0, 0, columnWidth, columnHeight); rect.offset(i * columnWidth, 0); @@ -159,8 +152,7 @@ public class FrequencyChart extends ScrollableChart } @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) - { + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(width, height); @@ -170,8 +162,7 @@ public class FrequencyChart extends ScrollableChart protected void onSizeChanged(int width, int height, int oldWidth, - int oldHeight) - { + int oldHeight) { if (height < 9) height = 200; baseSize = height / 8; @@ -191,15 +182,14 @@ public class FrequencyChart extends ScrollableChart paddingTop = 0; } - private void drawColumn(Canvas canvas, RectF rect, GregorianCalendar date) - { + private void drawColumn(Canvas canvas, RectF rect, GregorianCalendar date) { Integer values[] = frequency.get(new Timestamp(date)); float rowHeight = rect.height() / 8.0f; prevRect.set(rect); Integer[] localeWeekdayList = DateUtils.getLocaleWeekdayList(); - for (int j = 0; j < localeWeekdayList.length; j++) - { + + for (int j = 0; j < localeWeekdayList.length; j++) { rect.set(0, 0, baseSize, baseSize); rect.offset(prevRect.left, prevRect.top + baseSize * j); @@ -212,20 +202,18 @@ public class FrequencyChart extends ScrollableChart drawFooter(canvas, rect, date); } - private void drawFooter(Canvas canvas, RectF rect, GregorianCalendar date) - { + private void drawFooter(Canvas canvas, RectF rect, GregorianCalendar date) { Date time = date.getTime(); canvas.drawText(dfMonth.format(time), rect.centerX(), - rect.centerY() - 0.1f * em, pText); + 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); + rect.centerY() + 0.9f * em, pText); } - private void drawGrid(Canvas canvas, RectF rGrid) - { + private void drawGrid(Canvas canvas, RectF rGrid) { int nRows = 7; float rowHeight = rGrid.height() / (nRows + 1); @@ -233,14 +221,13 @@ public class FrequencyChart extends ScrollableChart pText.setColor(textColor); pGrid.setColor(gridColor); - for (String day : DateUtils.getLocaleDayNames(Calendar.SHORT)) - { + for (String day : DateUtils.getLocaleDayNames(Calendar.SHORT, firstWeekDay)) { canvas.drawText(day, rGrid.right - columnWidth, - rGrid.top + rowHeight / 2 + 0.25f * em, pText); + rGrid.top + rowHeight / 2 + 0.25f * em, pText); pGrid.setStrokeWidth(1f); canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top, - pGrid); + pGrid); rGrid.offset(0, rowHeight); } @@ -248,13 +235,12 @@ public class FrequencyChart extends ScrollableChart canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top, pGrid); } - private void drawMarker(Canvas canvas, RectF rect, Integer value) - { + private void drawMarker(Canvas canvas, RectF rect, Integer value) { float padding = rect.height() * 0.2f; // maximal allowed mark radius float maxRadius = (rect.height() - 2 * padding) / 2.0f; // the real mark radius is scaled down by a factor depending on the maximal frequency - float scale = 1.0f/maxFreq * value; + float scale = 1.0f / maxFreq * value; float radius = maxRadius * scale; int colorIndex = Math.min(colors.length - 1, Math.round((colors.length - 1) * scale)); @@ -262,13 +248,11 @@ public class FrequencyChart extends ScrollableChart canvas.drawCircle(rect.centerX(), rect.centerY(), radius, pGraph); } - private float getMaxMonthWidth() - { + private float getMaxMonthWidth() { float maxMonthWidth = 0; GregorianCalendar day = DateUtils.getStartOfTodayCalendar(); - for (int i = 0; i < 12; i++) - { + 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); @@ -277,16 +261,22 @@ public class FrequencyChart extends ScrollableChart return maxMonthWidth; } - private void init() - { + private void init() { initPaints(); initColors(); initDateFormats(); initRects(); + initFirstWeekDay(); + + } + + private void initFirstWeekDay() { + HabitsApplication app = (HabitsApplication) getContext().getApplicationContext(); + Preferences prefs = app.getComponent().getPreferences(); + firstWeekDay = prefs.getFirstWeekDay(); } - private void initColors() - { + private void initColors() { StyledResources res = new StyledResources(getContext()); textColor = res.getColor(R.attr.mediumContrastTextColor); gridColor = res.getColor(R.attr.lowContrastTextColor); @@ -298,27 +288,23 @@ public class FrequencyChart extends ScrollableChart colors[2] = ColorUtils.mixColors(colors[0], colors[3], 0.33f); } - private void initDateFormats() - { + private void initDateFormats() { dfMonth = AndroidDateFormats.fromSkeleton("MMM"); dfYear = AndroidDateFormats.fromSkeleton("yyyy"); } - private void initRects() - { + private void initRects() { rect = new RectF(); prevRect = new RectF(); } - public void populateWithRandomData() - { + public void populateWithRandomData() { GregorianCalendar date = DateUtils.getStartOfTodayCalendar(); date.set(Calendar.DAY_OF_MONTH, 1); Random rand = new Random(); frequency.clear(); - for (int i = 0; i < 40; i++) - { + for (int i = 0; i < 40; i++) { Integer values[] = new Integer[7]; for (int j = 0; j < 7; j++) values[j] = rand.nextInt(5); diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/HistoryChart.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/HistoryChart.java index 30e6b1731..33d87493b 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/HistoryChart.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/HistoryChart.java @@ -39,8 +39,7 @@ import java.util.*; import static org.isoron.androidbase.utils.InterfaceUtils.*; import static org.isoron.uhabits.core.models.Checkmark.*; -public class HistoryChart extends ScrollableChart -{ +public class HistoryChart extends ScrollableChart { private int[] checkmarks; private int target; @@ -97,42 +96,35 @@ public class HistoryChart extends ScrollableChart @NonNull private Controller controller; - private int weekFirstDay; + private int firstWeekDay; - public HistoryChart(Context context) - { + public HistoryChart(Context context) { super(context); init(); } - public HistoryChart(Context context, AttributeSet attrs) - { + public HistoryChart(Context context, AttributeSet attrs) { super(context, attrs); init(); } @Override - public void onLongPress(MotionEvent e) - { + public void onLongPress(MotionEvent e) { onSingleTapUp(e); } @Override - public boolean onSingleTapUp(MotionEvent e) - { + public boolean onSingleTapUp(MotionEvent e) { if (!isEditable) return false; performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); float x, y; - try - { + try { int pointerId = e.getPointerId(0); x = e.getX(pointerId); y = e.getY(pointerId); - } - catch (RuntimeException ex) - { + } catch (RuntimeException ex) { // Android often throws IllegalArgumentException here. Apparently, // the pointer id may become invalid shortly after calling // e.getPointerId. @@ -144,8 +136,7 @@ public class HistoryChart extends ScrollableChart Timestamp today = DateUtils.getToday(); int offset = timestamp.daysUntil(today); - if (offset < checkmarks.length) - { + if (offset < checkmarks.length) { boolean isChecked = checkmarks[offset] == CHECKED_EXPLICITLY; checkmarks[offset] = (isChecked ? UNCHECKED : CHECKED_EXPLICITLY); } @@ -155,16 +146,14 @@ public class HistoryChart extends ScrollableChart return true; } - public void populateWithRandomData() - { + public void populateWithRandomData() { 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++) - { + for (int i = 0; i < 100 - 7; i++) { int count = 0; for (int j = 0; j < 7; j++) if (checkmarks[i + j] != 0) count++; @@ -173,48 +162,40 @@ public class HistoryChart extends ScrollableChart } } - public void setCheckmarks(int[] checkmarks) - { + public void setCheckmarks(int[] checkmarks) { this.checkmarks = checkmarks; postInvalidate(); } - public void setColor(int color) - { + public void setColor(int color) { this.primaryColor = color; initColors(); postInvalidate(); } - public void setController(@NonNull Controller controller) - { + public void setController(@NonNull Controller controller) { this.controller = controller; } - public void setNumerical(boolean numerical) - { + public void setNumerical(boolean numerical) { isNumerical = numerical; } - public void setIsBackgroundTransparent(boolean isBackgroundTransparent) - { + public void setIsBackgroundTransparent(boolean isBackgroundTransparent) { this.isBackgroundTransparent = isBackgroundTransparent; initColors(); } - public void setIsEditable(boolean isEditable) - { + public void setIsEditable(boolean isEditable) { this.isEditable = isEditable; } - public void setTarget(int target) - { + public void setTarget(int target) { this.target = target; postInvalidate(); } - protected void initPaints() - { + protected void initPaints() { pTextHeader = new Paint(); pTextHeader.setTextAlign(Align.LEFT); pTextHeader.setAntiAlias(true); @@ -227,12 +208,11 @@ public class HistoryChart extends ScrollableChart } @Override - protected void onDraw(Canvas canvas) - { + protected void onDraw(Canvas canvas) { super.onDraw(canvas); baseLocation.set(0, 0, columnWidth - squareSpacing, - columnWidth - squareSpacing); + columnWidth - squareSpacing); baseLocation.offset(getPaddingLeft(), getPaddingTop()); headerOverflow = 0; @@ -243,8 +223,7 @@ public class HistoryChart extends ScrollableChart updateDate(); GregorianCalendar currentDate = (GregorianCalendar) baseDate.clone(); - for (int column = 0; column < nColumns - 1; column++) - { + for (int column = 0; column < nColumns - 1; column++) { drawColumn(canvas, baseLocation, currentDate, column); baseLocation.offset(columnWidth, -columnHeight); } @@ -253,8 +232,7 @@ public class HistoryChart extends ScrollableChart } @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) - { + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(width, height); @@ -264,8 +242,7 @@ public class HistoryChart extends ScrollableChart protected void onSizeChanged(int width, int height, int oldWidth, - int oldHeight) - { + int oldHeight) { if (height < 8) height = 200; float baseSize = height / 8.0f; setScrollerBucketSize((int) baseSize); @@ -286,40 +263,35 @@ public class HistoryChart extends ScrollableChart columnWidth = baseSize; columnHeight = 8 * baseSize; nColumns = - (int) ((width - rightLabelWidth - horizontalPadding) / baseSize) + - 1; + (int) ((width - rightLabelWidth - horizontalPadding) / baseSize) + + 1; updateDate(); } - private void drawAxis(Canvas canvas, RectF location) - { + private void drawAxis(Canvas canvas, RectF location) { float verticalOffset = pTextHeader.getFontSpacing() * 0.4f; - for (String day : DateUtils.getLocaleDayNames(Calendar.SHORT)) - { + for (String day : DateUtils.getLocaleDayNames(Calendar.SHORT, firstWeekDay)) { location.offset(0, columnWidth); canvas.drawText(day, location.left + headerTextOffset, - location.centerY() + verticalOffset, pTextHeader); + location.centerY() + verticalOffset, pTextHeader); } } private void drawColumn(Canvas canvas, RectF location, GregorianCalendar date, - int column) - { + int column) { drawColumnHeader(canvas, location, date); location.offset(0, columnWidth); - for (int j = 0; j < 7; j++) - { + for (int j = 0; j < 7; j++) { if (!(column == nColumns - 2 && getDataOffset() == 0 && - j > todayPositionInColumn)) - { + j > todayPositionInColumn)) { int checkmarkOffset = - getDataOffset() * 7 + nDays - 7 * (column + 1) + - todayPositionInColumn - j; + getDataOffset() * 7 + nDays - 7 * (column + 1) + + todayPositionInColumn - j; drawSquare(canvas, location, date, checkmarkOffset); } @@ -330,8 +302,7 @@ public class HistoryChart extends ScrollableChart private void drawColumnHeader(Canvas canvas, RectF location, - GregorianCalendar date) - { + GregorianCalendar date) { String month = dfMonth.format(date.getTime()); String year = dfYear.format(date.getTime()); @@ -339,12 +310,11 @@ public class HistoryChart extends ScrollableChart if (!month.equals(previousMonth)) text = previousMonth = month; else if (!year.equals(previousYear)) text = previousYear = year; - if (text != null) - { + if (text != null) { canvas.drawText(text, location.left + headerOverflow, - location.bottom - headerTextOffset, pTextHeader); + location.bottom - headerTextOffset, pTextHeader); headerOverflow += - pTextHeader.measureText(text) + columnWidth * 0.2f; + pTextHeader.measureText(text) + columnWidth * 0.2f; } headerOverflow = Math.max(0, headerOverflow - columnWidth); @@ -353,60 +323,54 @@ public class HistoryChart extends ScrollableChart private void drawSquare(Canvas canvas, RectF location, GregorianCalendar date, - int checkmarkOffset) - { + int checkmarkOffset) { if (checkmarkOffset >= checkmarks.length) pSquareBg.setColor(colors[0]); - else - { + else { int checkmark = checkmarks[checkmarkOffset]; - if(checkmark == 0) pSquareBg.setColor(colors[0]); - else if(checkmark < target) - { + if (checkmark == 0) pSquareBg.setColor(colors[0]); + else if (checkmark < target) { pSquareBg.setColor(isNumerical ? textColor : colors[1]); - } - else pSquareBg.setColor(colors[2]); + } else pSquareBg.setColor(colors[2]); } 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); + location.centerY() + squareTextOffset, pSquareFg); } - private float getWeekdayLabelWidth() - { + private float getWeekdayLabelWidth() { float width = 0; - for (String w : DateUtils.getLocaleDayNames(Calendar.SHORT)) + for (String w : DateUtils.getLocaleDayNames(Calendar.SHORT, firstWeekDay)) width = Math.max(width, pSquareFg.measureText(w)); return width; } - private void init() - { + private void init() { isEditable = false; checkmarks = new int[0]; - controller = new Controller() {}; + controller = new Controller() { + }; target = 2; initColors(); initPaints(); initDateFormats(); initRects(); - initWeekFirstDay(); + initFirstWeekDay(); } - private void initWeekFirstDay() { + private void initFirstWeekDay() { HabitsApplication app = (HabitsApplication) getContext().getApplicationContext(); Preferences prefs = app.getComponent().getPreferences(); - weekFirstDay = prefs.getWeekFirstDay(); + firstWeekDay = prefs.getFirstWeekDay(); } - private void initColors() - { + private void initColors() { StyledResources res = new StyledResources(getContext()); if (isBackgroundTransparent) @@ -416,41 +380,35 @@ public class HistoryChart extends ScrollableChart int green = Color.green(primaryColor); int blue = Color.blue(primaryColor); - if (isBackgroundTransparent) - { + 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 - { + } else { colors = new int[3]; colors[0] = res.getColor(R.attr.lowContrastTextColor); colors[1] = Color.argb(127, red, green, blue); colors[2] = primaryColor; textColor = res.getColor(R.attr.mediumContrastTextColor); reverseTextColor = - res.getColor(R.attr.highContrastReverseTextColor); + res.getColor(R.attr.highContrastReverseTextColor); } } - private void initDateFormats() - { + private void initDateFormats() { dfMonth = AndroidDateFormats.fromSkeleton("MMM"); dfYear = AndroidDateFormats.fromSkeleton("yyyy"); } - private void initRects() - { + private void initRects() { baseLocation = new RectF(); } @Nullable - private Timestamp positionToTimestamp(float x, float y) - { + private Timestamp positionToTimestamp(float x, float y) { int col = (int) (x / columnWidth); int row = (int) (y / columnWidth); @@ -462,31 +420,30 @@ public class HistoryChart extends ScrollableChart date.add(Calendar.DAY_OF_YEAR, offset); if (DateUtils.getStartOfDay(date.getTimeInMillis()) > - DateUtils.getStartOfToday()) return null; + DateUtils.getStartOfToday()) return null; return new Timestamp(date.getTimeInMillis()); } - private void updateDate() - { + private void updateDate() { baseDate = DateUtils.getStartOfTodayCalendar(); - baseDate.setFirstDayOfWeek(weekFirstDay); + baseDate.setFirstDayOfWeek(firstWeekDay); baseDate.add(Calendar.DAY_OF_YEAR, -(getDataOffset() - 1) * 7); nDays = (nColumns - 1) * 7; int realWeekday = - DateUtils.getStartOfTodayCalendar().get(Calendar.DAY_OF_WEEK); + DateUtils.getStartOfTodayCalendar().get(Calendar.DAY_OF_WEEK); todayPositionInColumn = - (7 + realWeekday - baseDate.getFirstDayOfWeek()) % 7; + (7 + realWeekday - baseDate.getFirstDayOfWeek()) % 7; baseDate.add(Calendar.DAY_OF_YEAR, -nDays); baseDate.add(Calendar.DAY_OF_YEAR, -todayPositionInColumn); } - public interface Controller - { - default void onToggleCheckmark(Timestamp timestamp) {} + public interface Controller { + default void onToggleCheckmark(Timestamp timestamp) { + } } } diff --git a/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java b/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java index 7c182dc36..3add5f25e 100644 --- a/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java +++ b/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java @@ -26,11 +26,10 @@ import org.isoron.uhabits.core.ui.*; import java.util.*; -public class Preferences -{ +public class Preferences { public static final String DEFAULT_SYNC_SERVER = - "https://sync.loophabits.org"; + "https://sync.loophabits.org"; @NonNull private final Storage storage; @@ -41,51 +40,41 @@ public class Preferences @Nullable private Boolean shouldReverseCheckmarks = null; - public Preferences(@NonNull Storage storage) - { + public Preferences(@NonNull Storage storage) { this.storage = storage; listeners = new LinkedList<>(); storage.onAttached(this); } - public void addListener(Listener listener) - { + public void addListener(Listener listener) { listeners.add(listener); } - public Integer getDefaultHabitColor(int fallbackColor) - { + public Integer getDefaultHabitColor(int fallbackColor) { return storage.getInt("pref_default_habit_palette_color", - fallbackColor); + fallbackColor); } - public HabitList.Order getDefaultOrder() - { + public HabitList.Order getDefaultOrder() { String name = storage.getString("pref_default_order", "BY_POSITION"); - try - { + try { return HabitList.Order.valueOf(name); - } - catch (IllegalArgumentException e) - { + } catch (IllegalArgumentException e) { setDefaultOrder(HabitList.Order.BY_POSITION); return HabitList.Order.BY_POSITION; } } - public void setDefaultOrder(HabitList.Order order) - { + public void setDefaultOrder(HabitList.Order order) { storage.putString("pref_default_order", order.name()); } - public int getDefaultScoreSpinnerPosition() - { + public int getDefaultScoreSpinnerPosition() { int defaultScoreInterval = - storage.getInt("pref_score_view_interval", 1); + storage.getInt("pref_score_view_interval", 1); - if (defaultScoreInterval > 5 || defaultScoreInterval < 0) - { + if (defaultScoreInterval > 5 || defaultScoreInterval < 0) { defaultScoreInterval = 1; storage.putInt("pref_score_view_interval", 1); } @@ -93,76 +82,62 @@ public class Preferences return defaultScoreInterval; } - public void setDefaultScoreSpinnerPosition(int position) - { + public void setDefaultScoreSpinnerPosition(int position) { storage.putInt("pref_score_view_interval", position); } - public int getLastHintNumber() - { + public int getLastHintNumber() { return storage.getInt("last_hint_number", -1); } - public Timestamp getLastHintTimestamp() - { + public Timestamp getLastHintTimestamp() { long unixTime = storage.getLong("last_hint_timestamp", -1); if (unixTime < 0) return null; else return new Timestamp(unixTime); } - public long getLastSync() - { + public long getLastSync() { return storage.getLong("last_sync", 0); } - public void setLastSync(long timestamp) - { + public void setLastSync(long timestamp) { storage.putLong("last_sync", timestamp); } - public boolean getShowArchived() - { + public boolean getShowArchived() { return storage.getBoolean("pref_show_archived", false); } - public void setShowArchived(boolean showArchived) - { + public void setShowArchived(boolean showArchived) { storage.putBoolean("pref_show_archived", showArchived); } - public boolean getShowCompleted() - { + public boolean getShowCompleted() { return storage.getBoolean("pref_show_completed", true); } - public void setShowCompleted(boolean showCompleted) - { + public void setShowCompleted(boolean showCompleted) { storage.putBoolean("pref_show_completed", showCompleted); } - public long getSnoozeInterval() - { + public long getSnoozeInterval() { return Long.parseLong(storage.getString("pref_snooze_interval", "15")); } - public int getWeekFirstDay() - { + public int getFirstWeekDay() { return Integer.parseInt(storage.getString("pref_week_start", "7")); } - public String getSyncAddress() - { + public String getSyncAddress() { return storage.getString("pref_sync_address", DEFAULT_SYNC_SERVER); } - public void setSyncAddress(String address) - { + public void setSyncAddress(String address) { storage.putString("pref_sync_address", address); for (Listener l : listeners) l.onSyncFeatureChanged(); } - public String getSyncClientId() - { + public String getSyncClientId() { String id = storage.getString("pref_sync_client_id", ""); if (!id.isEmpty()) return id; @@ -172,182 +147,152 @@ public class Preferences return id; } - public String getSyncKey() - { + public String getSyncKey() { return storage.getString("pref_sync_key", ""); } - public int getTheme() - { + public int getTheme() { return storage.getInt("pref_theme", ThemeSwitcher.THEME_LIGHT); } - public void setTheme(int theme) - { + public void setTheme(int theme) { storage.putInt("pref_theme", theme); } - public void incrementLaunchCount() - { + public void incrementLaunchCount() { storage.putInt("launch_count", getLaunchCount() + 1); } - public int getLaunchCount() - { + public int getLaunchCount() { return storage.getInt("launch_count", 0); } - public boolean isDeveloper() - { + public boolean isDeveloper() { return storage.getBoolean("pref_developer", false); } - public void setDeveloper(boolean isDeveloper) - { + public void setDeveloper(boolean isDeveloper) { storage.putBoolean("pref_developer", isDeveloper); } - public boolean isFirstRun() - { + public boolean isFirstRun() { return storage.getBoolean("pref_first_run", true); } - public void setFirstRun(boolean isFirstRun) - { + public void setFirstRun(boolean isFirstRun) { storage.putBoolean("pref_first_run", isFirstRun); } - public boolean isNumericalHabitsFeatureEnabled() - { + public boolean isNumericalHabitsFeatureEnabled() { return storage.getBoolean("pref_feature_numerical_habits", false); } - public boolean isPureBlackEnabled() - { + public boolean isPureBlackEnabled() { return storage.getBoolean("pref_pure_black", false); } - public boolean isShortToggleEnabled() - { + public boolean isShortToggleEnabled() { return storage.getBoolean("pref_short_toggle", false); } - public void setShortToggleEnabled(boolean enabled) - { + public void setShortToggleEnabled(boolean enabled) { storage.putBoolean("pref_short_toggle", enabled); } - public boolean isSyncEnabled() - { + public boolean isSyncEnabled() { return storage.getBoolean("pref_feature_sync", false); } - public void removeListener(Listener listener) - { + public void removeListener(Listener listener) { listeners.remove(listener); } - public void clear() - { + public void clear() { storage.clear(); } - public void setDefaultHabitColor(int color) - { + public void setDefaultHabitColor(int color) { storage.putInt("pref_default_habit_palette_color", color); } - public void setLastAppVersion(int version) - { + public void setLastAppVersion(int version) { storage.putInt("last_version", version); } - public void setNotificationsSticky(boolean sticky) - { + public void setNotificationsSticky(boolean sticky) { storage.putBoolean("pref_sticky_notifications", sticky); for (Listener l : listeners) l.onNotificationsChanged(); } - public void setNotificationsLed(boolean enabled) - { + public void setNotificationsLed(boolean enabled) { storage.putBoolean("pref_led_notifications", enabled); for (Listener l : listeners) l.onNotificationsChanged(); } - public void setCheckmarkSequenceReversed(boolean reverse) - { + public void setCheckmarkSequenceReversed(boolean reverse) { shouldReverseCheckmarks = reverse; storage.putBoolean("pref_checkmark_reverse_order", reverse); for (Listener l : listeners) l.onCheckmarkSequenceChanged(); } - public void setSyncEnabled(boolean isEnabled) - { + public void setSyncEnabled(boolean isEnabled) { storage.putBoolean("pref_feature_sync", isEnabled); - for(Listener l : listeners) l.onSyncFeatureChanged(); + for (Listener l : listeners) l.onSyncFeatureChanged(); } - public boolean shouldMakeNotificationsSticky() - { + public boolean shouldMakeNotificationsSticky() { return storage.getBoolean("pref_sticky_notifications", false); } - public boolean shouldMakeNotificationsLed() - { + public boolean shouldMakeNotificationsLed() { return storage.getBoolean("pref_led_notifications", false); } - public boolean isCheckmarkSequenceReversed() - { + public boolean isCheckmarkSequenceReversed() { if (shouldReverseCheckmarks == null) shouldReverseCheckmarks = - storage.getBoolean("pref_checkmark_reverse_order", false); + storage.getBoolean("pref_checkmark_reverse_order", false); return shouldReverseCheckmarks; } - public void updateLastHint(int number, Timestamp timestamp) - { + public void updateLastHint(int number, Timestamp timestamp) { storage.putInt("last_hint_number", number); storage.putLong("last_hint_timestamp", timestamp.getUnixTime()); } - public void setSyncKey(String key) - { + public void setSyncKey(String key) { storage.putString("pref_sync_key", key); - for(Listener l : listeners) l.onSyncFeatureChanged(); + for (Listener l : listeners) l.onSyncFeatureChanged(); } - public void setPureBlackEnabled(boolean enabled) - { + public void setPureBlackEnabled(boolean enabled) { storage.putBoolean("pref_pure_black", enabled); } - public int getLastAppVersion() - { + public int getLastAppVersion() { return storage.getInt("last_version", 0); } - public void setSnoozeInterval(int interval) - { + public void setSnoozeInterval(int interval) { storage.putString("pref_snooze_interval", String.valueOf(interval)); } - public void setNumericalHabitsFeatureEnabled(boolean enabled) - { + public void setNumericalHabitsFeatureEnabled(boolean enabled) { storage.putBoolean("pref_feature_numerical_habits", enabled); } - public interface Listener - { - default void onCheckmarkSequenceChanged() {} + public interface Listener { + default void onCheckmarkSequenceChanged() { + } - default void onNotificationsChanged() {} + default void onNotificationsChanged() { + } - default void onSyncFeatureChanged() {} + default void onSyncFeatureChanged() { + } } - public interface Storage - { + public interface Storage { void clear(); boolean getBoolean(String key, boolean defValue); diff --git a/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java b/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java index a03a6da43..2e80bcd58 100644 --- a/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java +++ b/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java @@ -27,8 +27,7 @@ import java.util.*; import static java.util.Calendar.*; -public abstract class DateUtils -{ +public abstract class DateUtils { private static Long fixedLocalTime = null; @@ -39,7 +38,7 @@ public abstract class DateUtils /** * Time of the day when the new day starts. */ - public static final int NEW_DAY_OFFSET = -9; + public static final int NEW_DAY_OFFSET = 3; /** * Number of milliseconds in one day. @@ -51,37 +50,32 @@ public abstract class DateUtils */ public static final long HOUR_LENGTH = 60 * 60 * 1000; - public static long applyTimezone(long localTimestamp) - { + public static long applyTimezone(long localTimestamp) { TimeZone tz = getTimezone(); return localTimestamp - tz.getOffset(localTimestamp - tz.getOffset(localTimestamp)); } - public static String formatHeaderDate(GregorianCalendar day) - { + public static String formatHeaderDate(GregorianCalendar day) { Locale locale = getLocale(); String dayOfMonth = Integer.toString(day.get(DAY_OF_MONTH)); String dayOfWeek = day.getDisplayName(DAY_OF_WEEK, SHORT, locale); return dayOfWeek + "\n" + dayOfMonth; } - private static GregorianCalendar getCalendar(long timestamp) - { + private static GregorianCalendar getCalendar(long timestamp) { GregorianCalendar day = new GregorianCalendar(TimeZone.getTimeZone("GMT"), getLocale()); day.setTimeInMillis(timestamp); return day; } - private static String[] getDayNames(int format) - { + private static String[] getDayNames(int format) { String[] wdays = new String[7]; Calendar day = new GregorianCalendar(); day.set(DAY_OF_WEEK, Calendar.SATURDAY); - for (int i = 0; i < wdays.length; i++) - { + for (int i = 0; i < wdays.length; i++) { wdays[i] = day.getDisplayName(DAY_OF_WEEK, format, getLocale()); day.add(DAY_OF_MONTH, 1); @@ -90,8 +84,7 @@ public abstract class DateUtils return wdays; } - public static long getLocalTime() - { + public static long getLocalTime() { if (fixedLocalTime != null) return fixedLocalTime; TimeZone tz = getTimezone(); @@ -103,14 +96,12 @@ public abstract class DateUtils * @return array with weekday names starting according to locale settings, * e.g. [Mo,Di,Mi,Do,Fr,Sa,So] in Germany */ - public static String[] getLocaleDayNames(int format) - { + public static String[] getLocaleDayNames(int format, int firstWeekDay) { String[] days = new String[7]; Calendar calendar = new GregorianCalendar(); - calendar.set(DAY_OF_WEEK, calendar.getFirstDayOfWeek()); - for (int i = 0; i < days.length; i++) - { + calendar.set(DAY_OF_WEEK, firstWeekDay); + for (int i = 0; i < days.length; i++) { days[i] = calendar.getDisplayName(DAY_OF_WEEK, format, getLocale()); calendar.add(DAY_OF_MONTH, 1); @@ -123,95 +114,80 @@ public abstract class DateUtils * @return array with week days numbers starting according to locale * settings, e.g. [2,3,4,5,6,7,1] in Europe */ - public static Integer[] getLocaleWeekdayList() - { + public static Integer[] getLocaleWeekdayList() { Integer[] dayNumbers = new Integer[7]; Calendar calendar = new GregorianCalendar(); calendar.set(DAY_OF_WEEK, calendar.getFirstDayOfWeek()); - for (int i = 0; i < dayNumbers.length; i++) - { + calendar.set(DAY_OF_WEEK, MONDAY); // NOT RESPONSIBLE + + for (int i = 0; i < dayNumbers.length; i++) { dayNumbers[i] = calendar.get(DAY_OF_WEEK); calendar.add(DAY_OF_MONTH, 1); } return dayNumbers; } - public static String[] getLongDayNames() - { + public static String[] getLongDayNames() { return getDayNames(GregorianCalendar.LONG); } - public static String[] getShortDayNames() - { + public static String[] getShortDayNames() { return getDayNames(SHORT); } @NonNull - public static Timestamp getToday() - { + public static Timestamp getToday() { return new Timestamp(getStartOfToday()); } - public static long getStartOfDay(long timestamp) - { + public static long getStartOfDay(long timestamp) { return (timestamp / DAY_LENGTH) * DAY_LENGTH; } - public static long getStartOfToday() - { + public static long getStartOfToday() { return getStartOfDay(getLocalTime() - NEW_DAY_OFFSET * HOUR_LENGTH); } - public static long millisecondsUntilTomorrow() - { + public static long millisecondsUntilTomorrow() { return getStartOfToday() + DAY_LENGTH - (getLocalTime() - NEW_DAY_OFFSET * HOUR_LENGTH); } - public static GregorianCalendar getStartOfTodayCalendar() - { + public static GregorianCalendar getStartOfTodayCalendar() { return getCalendar(getStartOfToday()); } - private static TimeZone getTimezone() - { - if(fixedTimeZone != null) return fixedTimeZone; + private static TimeZone getTimezone() { + if (fixedTimeZone != null) return fixedTimeZone; return TimeZone.getDefault(); } - public static void setFixedTimeZone(TimeZone tz) - { + public static void setFixedTimeZone(TimeZone tz) { fixedTimeZone = tz; } - public static long removeTimezone(long timestamp) - { + public static long removeTimezone(long timestamp) { TimeZone tz = getTimezone(); return timestamp + tz.getOffset(timestamp); } - public static void setFixedLocalTime(Long timestamp) - { + public static void setFixedLocalTime(Long timestamp) { fixedLocalTime = timestamp; } - public static void setFixedLocale(Locale locale) - { + public static void setFixedLocale(Locale locale) { fixedLocale = locale; } - private static Locale getLocale() - { - if(fixedLocale != null) return fixedLocale; + private static Locale getLocale() { + if (fixedLocale != null) return fixedLocale; return Locale.getDefault(); } - public static Long truncate(TruncateField field, long timestamp) - { + public static Long truncate(TruncateField field, long timestamp) { GregorianCalendar cal = DateUtils.getCalendar(timestamp); - switch (field) - { + switch (field) { case MONTH: cal.set(DAY_OF_MONTH, 1); return cal.getTimeInMillis(); @@ -240,8 +216,7 @@ public abstract class DateUtils } } - public enum TruncateField - { + public enum TruncateField { MONTH, WEEK_NUMBER, YEAR, QUARTER } } \ No newline at end of file