pebble/src/fw/applib/ui/date_time_selection_window_private.c
2025-01-27 11:38:16 -08:00

109 lines
3.5 KiB
C

/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "date_time_selection_window_private.h"
#include "services/common/clock.h"
#include "services/common/i18n/i18n.h"
#include "util/date.h"
#include "util/math.h"
#include <stdio.h>
static const int MIN_SELECTABLE_YEAR = 2010;
static const int MAX_SELECTABLE_YEAR = 2037; // Work around Y2038 problem
static int prv_wrap(int x, int max, int delta) {
x = (x + delta) % max;
return x < 0 ? x + max : x;
}
int date_time_selection_step_hour(int hour, int delta) {
return prv_wrap(hour, 24, delta);
}
int date_time_selection_step_minute(int minute, int delta) {
return prv_wrap(minute, 60, delta);
}
int date_time_selection_step_day(int year, int month, int day, int delta) {
bool is_leap_year = date_util_is_leap_year(year);
// This function expects Jan == 0, but date_util_get_max_days_in_month expects Jan == 1
int max_days = date_util_get_max_days_in_month(month + 1, is_leap_year);
// This functions expects the first day of the month is 1, but wrap expects the first day of the
// month is 0 (based off the mday element of the "tm" struct)
return prv_wrap(day - 1, max_days, delta) + 1;
}
int date_time_selection_step_month(int month, int delta) {
return prv_wrap(month, 12, delta);
}
int date_time_selection_truncate_date(int year, int month, int day) {
bool is_leap_year = date_util_is_leap_year(year);
// date_util_get_max_days_in_month expects Jan == 1, but this function expects Jan == 0
int max_days = date_util_get_max_days_in_month(month + 1, is_leap_year);
return MIN(day, max_days);
}
int date_time_selection_step_year(int year, int delta) {
year += delta;
return CLIP(year, MIN_SELECTABLE_YEAR - STDTIME_YEAR_OFFSET,
MAX_SELECTABLE_YEAR - STDTIME_YEAR_OFFSET);
}
char *date_time_selection_get_text(TimeData *data, TimeInputIndex index, char *buf) {
switch (index) {
case TimeInputIndexHour: {
unsigned hour = data->hour;
if (!clock_is_24h_style()) {
hour = hour % 12;
if (hour == 0) {
hour = 12;
}
}
snprintf(buf, 3, "%02u", hour);
return buf;
}
case TimeInputIndexMinute:
snprintf(buf, 3, "%02u", data->minute);
return buf;
case TimeInputIndexAMPM: // We should only get this in 12h style
if (data->hour < 12) {
i18n_get_with_buffer("AM", buf, 3);
} else {
i18n_get_with_buffer("PM", buf, 3);
}
return buf;
default:
return "";
}
}
void date_time_handle_time_change(TimeData *data, TimeInputIndex index, int delta) {
switch (index) {
case TimeInputIndexHour:
data->hour = date_time_selection_step_hour(data->hour, delta);
break;
case TimeInputIndexMinute:
data->minute = date_time_selection_step_minute(data->minute, delta);
break;
case TimeInputIndexAMPM: // We should only get this in 12h style
data->hour = date_time_selection_step_hour(data->hour, 12 * delta);
break;
}
}