Upload files to "src/c"
This commit is contained in:
7
src/c/num2words.h
Normal file
7
src/c/num2words.h
Normal file
@@ -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);
|
||||
72
src/c/options.c
Normal file
72
src/c/options.c
Normal file
@@ -0,0 +1,72 @@
|
||||
#include <pebble.h>
|
||||
#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
|
||||
}
|
||||
5
src/c/options.h
Normal file
5
src/c/options.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#define KEY_OPTIONS 99
|
||||
|
||||
void init_options();
|
||||
477
src/c/sliding_time_wd.c
Normal file
477
src/c/sliding_time_wd.c
Normal file
@@ -0,0 +1,477 @@
|
||||
#include <pebble.h>
|
||||
#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();
|
||||
}
|
||||
97
src/c/sliding_time_wd.h
Normal file
97
src/c/sliding_time_wd.h
Normal file
@@ -0,0 +1,97 @@
|
||||
#include <pebble.h>
|
||||
|
||||
|
||||
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;
|
||||
Reference in New Issue
Block a user