From 5db5da362e1602a47662cfa67265b05c36d6db27 Mon Sep 17 00:00:00 2001 From: alanacheff Date: Sun, 6 Oct 2024 21:24:05 +0000 Subject: [PATCH] Upload files to "src/c" --- src/c/num2words.h | 7 + src/c/options.c | 72 ++++++ src/c/options.h | 5 + src/c/sliding_time_wd.c | 477 ++++++++++++++++++++++++++++++++++++++++ src/c/sliding_time_wd.h | 97 ++++++++ 5 files changed, 658 insertions(+) create mode 100644 src/c/num2words.h create mode 100644 src/c/options.c create mode 100644 src/c/options.h create mode 100644 src/c/sliding_time_wd.c create mode 100644 src/c/sliding_time_wd.h diff --git a/src/c/num2words.h b/src/c/num2words.h new file mode 100644 index 0000000..8445564 --- /dev/null +++ b/src/c/num2words.h @@ -0,0 +1,7 @@ +#pragma once + +void time_to_common_words(int hours, int minutes, char *words); +void fuzzy_time_to_words(int hours, int minutes, char* words); +void minute_to_formal_words(int minutes, int displayPrefix, char *first_word, char *second_word); +void hour_to_12h_word(int hours, char *word); +void hour_to_24h_word(int hours, char *words); \ No newline at end of file diff --git a/src/c/options.c b/src/c/options.c new file mode 100644 index 0000000..9fd1d41 --- /dev/null +++ b/src/c/options.c @@ -0,0 +1,72 @@ +#include +#include "options.h" +#include "constants.h" +#include "sliding_time_wd.h" + +extern Options s_options; + +void init_options() { + + if (persist_exists(KEY_OPTIONS)) { + persist_read_data(KEY_OPTIONS, &s_options, sizeof(s_options)); + } + else { + s_options.shake_for_lohi = DEFAULT_SHAKE_FOR_LOHI; + s_options.weatherdate_alignment = DEFAULT_WEATHERDATE_ALIGNMENT; + s_options.hourminute_alignment = DEFAULT_HOURMINUTES_ALIGNMENT; + s_options.display_weather = DEFAULT_DISPLAY_WEATHER; + s_options.use_celsius = DEFAULT_USE_CELSIUS; + s_options.weather_use_GPS = DEFAULT_WEATHER_USE_GPS; + memset(s_options.weather_location, 0,sizeof(s_options.weather_location)); + s_options.weather_frequency = DEFAULT_WEATHER_FREQUENCY; + s_options.min_since_last_forecast = DEFAULT_MIN_SINCE_WEATHER_UPDATE; + s_options.display_prefix = DEFAULT_DISPLAY_O_PREFIX; + s_options.time_color = DEFAULT_TIME_COLOR; + s_options.hr_color = DEFAULT_HR_COLOR; + s_options.min_color = DEFAULT_MIN_COLOR; + s_options.wd_color = DEFAULT_WD_COLOR; + s_options.background_color = DEFAULT_BACKGROUND_COLOR; + s_options.weatherdate_readability = DEFAULT_WEATHERDATE_READABILITY; + s_options.minutes_readability = DEFAULT_MINUTES_READABILITY; + s_options.condition_code = DEFAULT_CONDITION_CODE; + s_options.vibrate_bt_status = DEFAULT_VIBRATE_BT_STATUS; + s_options.display_date = DEFAULT_DISPLAY_DATE; + memset(s_options.conditions, 0,sizeof(s_options.conditions)); + snprintf(s_options.last_weather_update12hr, sizeof(s_options.last_weather_update12hr), DEFAULT_LAST_WEATHER_UPDATE); + snprintf(s_options.last_weather_update24hr, sizeof(s_options.last_weather_update24hr), DEFAULT_LAST_WEATHER_UPDATE); + //persist_write_data(KEY_OPTIONS, &s_options, sizeof(s_options)); + } + #if DEBUG + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.shake_for_lohi: %d", s_options.shake_for_lohi); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.tempF: %d", s_options.tempF); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.tempFLo: %d", s_options.tempFLo); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.tempFHi: %d", s_options.tempFHi); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.tempC: %d", s_options.tempC); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.tempCLo: %d", s_options.tempCLo); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.tempCHi: %d", s_options.tempCHi); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.weatherdate_alignment: %d", s_options.weatherdate_alignment); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.hourminute_alignment: %d", s_options.hourminute_alignment); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.display_weather: %d", s_options.display_weather); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.display_date: %d", s_options.display_date); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.use_celsius: %d", s_options.use_celsius); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.weather_use_GPS: %d", s_options.weather_use_GPS); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.weather_location: %s", s_options.weather_location); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.weather_frequency: %d", s_options.weather_frequency); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.min_since_last_forecast: %d", s_options.min_since_last_forecast); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.display_prefix: %d", s_options.display_prefix); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.time_color: %d", s_options.time_color); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.hr_color: %d", s_options.hr_color); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.min_color: %d", s_options.min_color); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.wd_color: %d", s_options.wd_color); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.background_color: %d", s_options.background_color); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.weatherdate_readability: %d", s_options.weatherdate_readability); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.minutes_readability: %d", s_options.minutes_readability); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.condition_code: %d", s_options.condition_code); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.bluetooth_state: %d", s_options.bluetooth_state); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.vibrate_bt_status: %d", s_options.vibrate_bt_status); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.conditions: %s", s_options.conditions); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.last_weather_update12hr: %s", s_options.last_weather_update12hr); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.last_weather_update24hr: %s", s_options.last_weather_update24hr); + APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: options sizeof(s_options) %zu", sizeof(s_options)); + #endif +} \ No newline at end of file diff --git a/src/c/options.h b/src/c/options.h new file mode 100644 index 0000000..f1d00d9 --- /dev/null +++ b/src/c/options.h @@ -0,0 +1,5 @@ +#pragma once + +#define KEY_OPTIONS 99 + + void init_options(); \ No newline at end of file diff --git a/src/c/sliding_time_wd.c b/src/c/sliding_time_wd.c new file mode 100644 index 0000000..3d80293 --- /dev/null +++ b/src/c/sliding_time_wd.c @@ -0,0 +1,477 @@ +#include +#include "sliding_time_wd.h" +#include "constants.h" +#include "num2words.h" +#include "options.h" +#include "weather_date.h" +#include "messaging.h" + +Options s_options; +SlidingTextData *s_data; + +//stores weather retry counts (incremented in second tick handler). +//Stop retry count at DEFAULT_MAX_WEATHER_RETRY_COUNT +int g_weather_retry_count = 0; + +GTextAlignment row_alignment(int alignment) { + switch (alignment) { + case 0: return GTextAlignmentLeft; + case 1: return GTextAlignmentCenter; + case 2: return GTextAlignmentRight; + default: return GTextAlignmentLeft; + } +} + +void set_time_layers_color(GColor textColor) { + SlidingTextData *data = s_data; + SlidingRow *row; + + for (size_t i = 0; i < ARRAY_LENGTH(data->rows); ++i) { + row = &data->rows[i]; + text_layer_set_text_color(row->label, textColor); + } +} + +void set_hr_layer_color(GColor textColor) { + SlidingTextData *data = s_data; + SlidingRow *row; + + row = &data->rows[HOUR_ROW]; + text_layer_set_text_color(row->label, textColor); +} + +void set_min_layers_color(GColor textColor) { + SlidingTextData *data = s_data; + SlidingRow *row; + + row = &data->rows[MINUTE_ROW1]; + text_layer_set_text_color(row->label, textColor); + + row = &data->rows[MINUTE_ROW2]; + text_layer_set_text_color(row->label, textColor); +} + +void set_wd_layers_color(GColor textColor) { + text_layer_set_text_color(weather_layer1, textColor); + #if defined(PBL_ROUND) + text_layer_set_text_color(weather_layer2, textColor); + text_layer_set_text_color(weather_layer_center, textColor); + #endif + text_layer_set_text_color(date_layer, textColor); +} + +static void init_window_background_color(){ + SlidingTextData *data = s_data; + + window_set_background_color(data->window, GColorBlack); + #ifdef PBL_COLOR // If on basalt + window_set_background_color(data->window, GColorFromHEX(s_options.background_color)); + #else + if (s_options.background_color == 0xFFFFFF) { + window_set_background_color(data->window, GColorWhite);//white + } + else if (s_options.background_color == 0x000000) {//black + window_set_background_color(data->window, GColorBlack); + } + else { //didn't select white or black, default to white + window_set_background_color(data->window, GColorBlack); + } + #endif +} + +static void init_sliding_row(SlidingTextData *data, SlidingRow *row, GRect pos, GFont font, + int delay, int layerColor) { + row->label = text_layer_create(pos); + + //set row alignment + text_layer_set_text_alignment(row->label, row_alignment(s_options.hourminute_alignment)); + + text_layer_set_background_color(row->label, GColorClear); + text_layer_set_text_color(row->label, GColorWhite); + text_layer_set_text_color(row->label, GColorFromHEX(layerColor)); + + if (font) { + text_layer_set_font(row->label, font); + row->unchanged_font = true; + } else { + row->unchanged_font = false; + } + + row->state = IN_FRAME; + row->next_string = NULL; + + row->left_pos = -pos.size.w; + row->right_pos = pos.size.w; + row->still_pos = pos.origin.x; + + row->movement_delay = delay; + row->delay_count = 0; + + data->last_hour = -1; + data->last_minute = -1; +} + +void init_static_row(TextLayer *label, GFont font) { + + //set row alignment + #if defined(PBL_RECT) + text_layer_set_text_alignment(label, row_alignment(s_options.weatherdate_alignment)); + #elif defined(PBL_ROUND) + text_layer_set_text_alignment(label, row_alignment(DEFAULT_CHALK_ALIGNMENT)); + #endif + + text_layer_set_background_color(label, GColorClear); + text_layer_set_text_color(label, GColorWhite); + text_layer_set_text_color(label, GColorFromHEX(s_options.wd_color)); + + if (font) { + text_layer_set_font(label, font); + } +} + +static void slide_in_text(SlidingTextData *data, SlidingRow *row, char* new_text) { + (void) data; + + const char *old_text = text_layer_get_text(row->label); + if (old_text) { + row->next_string = new_text; + row->state = PREPARE_TO_MOVE; + } else { + text_layer_set_text(row->label, new_text); + GRect frame = layer_get_frame(text_layer_get_layer(row->label)); + frame.origin.x = row->right_pos; + layer_set_frame(text_layer_get_layer(row->label), frame); + row->state = MOVING_IN; + } +} + +static bool update_sliding_row(SlidingTextData *data, SlidingRow *row) { + (void) data; + + GRect frame = layer_get_frame(text_layer_get_layer(row->label)); + bool something_changed = true; + switch (row->state) { + case PREPARE_TO_MOVE: + frame.origin.x = row->still_pos; + row->delay_count++; + if (row->delay_count > row->movement_delay) { + row->state = MOVING_OUT; + row->delay_count = 0; + } + break; + + case MOVING_IN: { + int speed = abs(frame.origin.x - row->still_pos) / 3 + 1; + frame.origin.x -= speed; + if (frame.origin.x <= row->still_pos) { + frame.origin.x = row->still_pos; + row->state = IN_FRAME; + } + } + break; + + case MOVING_OUT: { + int speed = abs(frame.origin.x - row->still_pos) / 3 + 1; + frame.origin.x -= speed; + + if (frame.origin.x <= row->left_pos) { + frame.origin.x = row->right_pos; + row->state = MOVING_IN; + text_layer_set_text(row->label, row->next_string); + row->next_string = NULL; + } + } + break; + + case IN_FRAME: + default: + something_changed = false; + break; + } + if (something_changed) { + layer_set_frame(text_layer_get_layer(row->label), frame); + } + return something_changed; +} + +static void animation_update(struct Animation *animation, const AnimationProgress time_normalized) { + SlidingTextData *data = s_data; + + struct SlidingTextRenderState *rs = &data->render_state; + + time_t now = time(NULL); + struct tm t = *localtime(&now); + + bool something_changed = false; + + if (data->last_minute != t.tm_min) { + something_changed = true; + + minute_to_formal_words(t.tm_min, s_options.display_prefix, rs->first_minutes[rs->next_minutes], rs->second_minutes[rs->next_minutes]); + if(data->last_hour != t.tm_hour || t.tm_min <= 20 + || t.tm_min/10 != data->last_minute/10) { + slide_in_text(data, &data->rows[MINUTE_ROW1], rs->first_minutes[rs->next_minutes]); + } else { + // The tens line didn't change, so swap to the correct buffer but don't animate + text_layer_set_text(data->rows[MINUTE_ROW1].label, rs->first_minutes[rs->next_minutes]); + } + slide_in_text(data, &data->rows[MINUTE_ROW2], rs->second_minutes[rs->next_minutes]); + rs->next_minutes = rs->next_minutes ? 0 : 1; + data->last_minute = t.tm_min; + } + + if (data->last_hour != t.tm_hour) { + hour_to_12h_word(t.tm_hour, rs->hours[rs->next_hours]); + slide_in_text(data, &data->rows[HOUR_ROW], rs->hours[rs->next_hours]); + rs->next_hours = rs->next_hours ? 0 : 1; + data->last_hour = t.tm_hour; + } + + for (size_t i = 0; i < ARRAY_LENGTH(data->rows); ++i) { + something_changed = update_sliding_row(data, &data->rows[i]) || something_changed; + } + + if (!something_changed) { + animation_unschedule(data->animation); + #ifdef PBL_SDK_2 + animation_destroy(s_data->animation); + #endif + } +} + +static void make_animation() { + s_data->animation = animation_create(); + animation_set_duration(s_data->animation, ANIMATION_DURATION_INFINITE); + // the animation will stop itself + static const struct AnimationImplementation s_animation_implementation = { + .update = animation_update, + }; + animation_set_implementation(s_data->animation, &s_animation_implementation); + animation_schedule(s_data->animation); +} + +static void bt_handler(bool isConnected) { + int current_bluetooth_state = 0; //default bluetooth disconnected + if (isConnected) + current_bluetooth_state = 1; //bluetooth connected + + //if bluetooth was previously connected and is now disconnected + if (s_options.bluetooth_state == 1 && + current_bluetooth_state == 0) { + + if (s_options.vibrate_bt_status) { + vibes_short_pulse(); //vibrate on bt disconnect, if option enabled + } + } + + //if bluetooth was previously disconnected and is now connected + if (s_options.bluetooth_state == 0 && + current_bluetooth_state == 1) { + + //clear weather conditions and reset weather retry count to force weather update + memset(s_options.conditions, 0,sizeof(s_options.conditions)); + s_options.condition_code = DEFAULT_CONDITION_CODE; + g_weather_retry_count = 0; + } + + //store bluetooth state + s_options.bluetooth_state = current_bluetooth_state; +} + +static void tap_handler(AccelAxisType axis, int32_t direction) { + if (s_options.shake_for_lohi == 1) { + //Display Lo Hi temp info; + display_lohi_weather_info(); + } +} + +//every five seconds +static void handle_5second_tick(struct tm *tick_time, TimeUnits units_changed) { + + //if conditions blank (no current weather info) + if(strlen(s_options.conditions) == 0 && + g_weather_retry_count < DEFAULT_MAX_WEATHER_RETRY_COUNT) { + + //add one to weather retry count - stop trying this app session at DEFAULT_MAX_WEATHER_RETRY_COUNT + ++g_weather_retry_count; + + //reset time since last forecast timer + s_options.min_since_last_forecast = 0; + + //get updated weather + send(KEY_GET_WEATHER, 1, KEY_WEATHER_USE_GPS, s_options.weather_use_GPS, KEY_WEATHER_LOCATION, s_options.weather_location); + + + //update weather layer + update_weather_layer(); + } + //APP_LOG(APP_LOG_LEVEL_DEBUG, "heap_bytes_free:heap_bytes_used %zu: %zu", heap_bytes_free(), heap_bytes_used()); +} + +//every minute +static void handle_minute_tick(struct tm *tick_time, TimeUnits units_changed) { + + if (units_changed & DAY_UNIT) { + //vibes_double_pulse(); //hourly vibration + } + + make_animation(); //animate mew time + update_date_layer(); //check/update date layer + + //get minutes since last weather update + time_t t = time(NULL); + int min_since_last_update = (difftime(t, s_options.last_update) / 60) + 1; + + APP_LOG(APP_LOG_LEVEL_DEBUG, " (Last update %s) handle_minute_tick min_since_last_update:weather_frequency - %d:%d", s_options.last_weather_update24hr, min_since_last_update, s_options.weather_frequency); + //APP_LOG(APP_LOG_LEVEL_DEBUG, "handle_minute_tick strlen(s_options.conditions): %zu", strlen(s_options.conditions)); + //if min_since_last_forecast greater than or equal to weatherUpdateFrequency + if(min_since_last_update >= s_options.weather_frequency || + strlen(s_options.conditions) == 0) { + + s_options.min_since_last_forecast = 0; + + //get updated weather + send(KEY_GET_WEATHER, 1, KEY_WEATHER_USE_GPS, s_options.weather_use_GPS, KEY_WEATHER_LOCATION, s_options.weather_location); + + //update weather layer + update_weather_layer(); + } +} + + +void handle_tick(struct tm *tick_time, TimeUnits units_changed) { + if (units_changed & SECOND_UNIT) { + if (tick_time->tm_sec % 5 == 0) { + handle_5second_tick(tick_time, units_changed); + } + } + if (units_changed & MINUTE_UNIT) { + handle_minute_tick(tick_time, units_changed); + } +} + +static void handle_deinit(void) { + + //save watchface options + persist_write_data(KEY_OPTIONS, &s_options, sizeof(s_options)); + + text_layer_destroy(weather_layer1); + #if defined(PBL_ROUND) + text_layer_destroy(weather_layer_center); + text_layer_destroy(weather_layer2); + #endif + text_layer_destroy(date_layer); + + #ifdef PBL_SDK_2 + bluetooth_connection_service_unsubscribe(); + #elif PBL_SDK_3 + connection_service_unsubscribe(); + #endif + + accel_tap_service_unsubscribe(); + tick_timer_service_unsubscribe(); + + free(s_data); +} + +static void handle_init() { + SlidingTextData *data = (SlidingTextData*)malloc(sizeof(SlidingTextData)); + s_data = data; + + g_weather_retry_count = 0; + + int chalk_time_X_offset = 0; + int chalk_time_Y_offset = 0; + + #if defined(PBL_RECT) + chalk_time_X_offset = 0; + chalk_time_Y_offset = 0; + #elif defined(PBL_ROUND) + chalk_time_X_offset = DEFAULT_CHALK_TIME_X_OFFSET; + chalk_time_Y_offset = DEFAULT_CHALK_TIME_Y_OFFSET; + #endif + + data->render_state.next_hours = 0; + data->render_state.next_minutes = 0; + data->render_state.demo_time.secs = 0; + data->render_state.demo_time.mins = 0; + data->render_state.demo_time.hour = 0; + + data->window = window_create(); + Layer *window_layer = window_get_root_layer(data->window); + GRect layer_frame = layer_get_frame(window_layer); + const int16_t width = layer_frame.size.w; + + //set-retrieve watchface options + init_options(); + + init_window_background_color(); + + data->hour_text = fonts_get_system_font(FONT_KEY_BITHAM_42_BOLD); + if (s_options.minutes_readability) { + data->minute_text = fonts_get_system_font(FONT_KEY_BITHAM_42_BOLD); + } + else { + data->minute_text = fonts_get_system_font(FONT_KEY_BITHAM_42_LIGHT); + } + + //init hour/minutes layers + init_sliding_row(data, &data->rows[HOUR_ROW], GRect(0 + chalk_time_X_offset, 20 + chalk_time_Y_offset, width - (chalk_time_X_offset * 2), 60), data->hour_text, 6, s_options.hr_color); + layer_add_child(window_layer, text_layer_get_layer(data->rows[HOUR_ROW].label)); + + init_sliding_row(data, &data->rows[MINUTE_ROW1], GRect(0 + chalk_time_X_offset, 56 + chalk_time_Y_offset, width - (chalk_time_X_offset * 2), 96), data->minute_text, 3, s_options.min_color); + layer_add_child(window_layer, text_layer_get_layer(data->rows[MINUTE_ROW1].label)); + + init_sliding_row(data, &data->rows[MINUTE_ROW2], GRect(0 + chalk_time_X_offset, 92 + chalk_time_Y_offset, width - (chalk_time_X_offset * 2), 132), data->minute_text, 0, s_options.min_color); + layer_add_child(window_layer, text_layer_get_layer(data->rows[MINUTE_ROW2].label)); + + //add weather and date layers + add_weatherdate_layers(window_layer, width); + + GFont norm14 = fonts_get_system_font(FONT_KEY_GOTHIC_14); + + data->demo_label = text_layer_create(GRect(0, -3, 100, 20)); + text_layer_set_background_color(data->demo_label, GColorClear); + text_layer_set_text_color(data->demo_label, GColorWhite); + text_layer_set_font(data->demo_label, norm14); + text_layer_set_text(data->demo_label, "demo mode"); + layer_add_child(window_layer, text_layer_get_layer(data->demo_label)); + + layer_set_hidden(text_layer_get_layer(data->demo_label), true); + layer_mark_dirty(window_layer); + + app_message_register_inbox_received(inbox_received_callback); + app_message_register_inbox_dropped(message_dropped); + app_message_register_outbox_sent(message_out_success); + app_message_register_outbox_failed(message_out_failed); + + #if defined(PBL_BW) + app_message_open(175, 250); + #else + app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum()); + #endif + + update_date_layer(); //update date_layer + update_weather_layer(); //update weather layer + make_animation(); //animate new time layers + + tick_timer_service_subscribe(MINUTE_UNIT | SECOND_UNIT, handle_tick); + accel_tap_service_subscribe(tap_handler); + + // Subscribe to Bluetooth updates + connection_service_subscribe((ConnectionHandlers) { + .pebble_app_connection_handler = bt_handler + }); + + // Check current bluetooth connection state + bt_handler(connection_service_peek_pebble_app_connection()); + + const bool animated = true; + window_stack_push(data->window, animated); +} + +int main(void) { + handle_init(); + app_event_loop(); + handle_deinit(); +} \ No newline at end of file diff --git a/src/c/sliding_time_wd.h b/src/c/sliding_time_wd.h new file mode 100644 index 0000000..03ce391 --- /dev/null +++ b/src/c/sliding_time_wd.h @@ -0,0 +1,97 @@ +#include + + +TextLayer *weather_layer1, *weather_layer2, *weather_layer_center, *date_layer; +AppTimer *lohi_display_timer; + +void init_static_row(TextLayer *label, GFont font); //creates/configures static (weather/date) display lines +GTextAlignment row_alignment(int alignment); //accepts int alignement and sets row GTextAlignment (0 left, 1 center, 2 right) +void set_time_layers_color(GColor textColor); +void set_hr_layer_color(GColor textColor); +void set_min_layers_color(GColor textColor); +void set_wd_layers_color(GColor textColor); + +typedef struct { + int shake_for_lohi; + int tempF; + int tempFLo; + int tempFHi; + int tempC; + int tempCLo; + int tempCHi; + int weatherdate_alignment; + int hourminute_alignment; + int display_weather; + int weather_use_GPS; + char weather_location[64]; + int use_celsius; + int weather_frequency; + int min_since_last_forecast; + int display_prefix; + int time_color; + int hr_color; + int min_color; + int wd_color; + int background_color; + int weatherdate_readability; + int minutes_readability; + int condition_code; + int vibrate_bt_status; + int pebble_js_ready; + int display_date; + bool bluetooth_state; + time_t last_update; + char conditions[32]; + char last_weather_update12hr[16]; + char last_weather_update24hr[16]; +} Options; + +typedef enum { + MOVING_IN, + IN_FRAME, + PREPARE_TO_MOVE, + MOVING_OUT +} SlideState; + +typedef struct { + TextLayer *label; + SlideState state; // animation state + char *next_string; // what to say in the next phase of animation + bool unchanged_font; + + int left_pos; + int right_pos; + int still_pos; + + int movement_delay; + int delay_count; +} SlidingRow; + +typedef struct { + TextLayer *demo_label; + SlidingRow rows[3]; + int last_hour; + int last_minute; + + GFont hour_text; + GFont minute_text; + + Window *window; + Animation *animation; + + struct SlidingTextRenderState { + // double buffered string storage + char hours[2][32]; + uint8_t next_hours; + char first_minutes[2][32]; + char second_minutes[2][32]; + uint8_t next_minutes; + + struct SlidingTextRenderDemoTime { + int secs; + int mins; + int hour; + } demo_time; + } render_state; + +} SlidingTextData; \ No newline at end of file