Half-baked timeline peak support
@@ -9,7 +9,7 @@ Want something more personal? Everything is individually configurable, including
|
||||
Some optional features include the display of unlit segments behind the time, shake to see the date (configurable timeout), and time color shift on BT disconnect.
|
||||
|
||||
Warning light legend:
|
||||
- Lit "E" icon: low fuel (battery)
|
||||
- Lit "E" and "F" icons: low fuel (battery)
|
||||
- Lit "C" and "H" icons: temperature fetch failure
|
||||
- Lit time/date digits: BT connection lost (this feature is off by default)
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"messageKeys": [
|
||||
"PKJS_READY",
|
||||
"PKJS_TEMP_BAR_COUNT",
|
||||
"CLAY_ENABLE_PEEK",
|
||||
"CLAY_BT_INDICATOR",
|
||||
"CLAY_SHOW_TIME_MG",
|
||||
"CLAY_USE_CUSTOM_LED",
|
||||
@@ -156,6 +157,83 @@
|
||||
"name": "SUPER8",
|
||||
"spaceOptimization": "storage",
|
||||
"type": "bitmap"
|
||||
},
|
||||
{
|
||||
"file": "0_m.png",
|
||||
"memoryFormat": "Smallest",
|
||||
"name": "0_M",
|
||||
"spaceOptimization": "storage",
|
||||
"type": "bitmap"
|
||||
},
|
||||
{
|
||||
"file": "1_m.png",
|
||||
"memoryFormat": "Smallest",
|
||||
"name": "1_M",
|
||||
"spaceOptimization": "storage",
|
||||
"type": "bitmap"
|
||||
},
|
||||
{
|
||||
"file": "2_m.png",
|
||||
"memoryFormat": "Smallest",
|
||||
"name": "2_M",
|
||||
"spaceOptimization": "storage",
|
||||
"type": "bitmap"
|
||||
},
|
||||
{
|
||||
"file": "3_m.png",
|
||||
"memoryFormat": "Smallest",
|
||||
"name": "3_M",
|
||||
"spaceOptimization": "storage",
|
||||
"type": "bitmap"
|
||||
},
|
||||
{
|
||||
"file": "4_m.png",
|
||||
"memoryFormat": "Smallest",
|
||||
"name": "4_M",
|
||||
"spaceOptimization": "storage",
|
||||
"type": "bitmap"
|
||||
},
|
||||
{
|
||||
"file": "5_m.png",
|
||||
"memoryFormat": "Smallest",
|
||||
"name": "5_M",
|
||||
"spaceOptimization": "storage",
|
||||
"type": "bitmap"
|
||||
},
|
||||
{
|
||||
"file": "6_m.png",
|
||||
"memoryFormat": "Smallest",
|
||||
"name": "6_M",
|
||||
"spaceOptimization": "storage",
|
||||
"type": "bitmap"
|
||||
},
|
||||
{
|
||||
"file": "7_m.png",
|
||||
"memoryFormat": "Smallest",
|
||||
"name": "7_M",
|
||||
"spaceOptimization": "storage",
|
||||
"type": "bitmap"
|
||||
},
|
||||
{
|
||||
"file": "8_m.png",
|
||||
"memoryFormat": "Smallest",
|
||||
"name": "8_M",
|
||||
"spaceOptimization": "storage",
|
||||
"type": "bitmap"
|
||||
},
|
||||
{
|
||||
"file": "9_m.png",
|
||||
"memoryFormat": "Smallest",
|
||||
"name": "9_M",
|
||||
"spaceOptimization": "storage",
|
||||
"type": "bitmap"
|
||||
},
|
||||
{
|
||||
"file": "super8_m.png",
|
||||
"memoryFormat": "Smallest",
|
||||
"name": "SUPER8_M",
|
||||
"spaceOptimization": "storage",
|
||||
"type": "bitmap"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 230 B |
|
After Width: | Height: | Size: 179 B |
|
After Width: | Height: | Size: 250 B |
|
After Width: | Height: | Size: 229 B |
|
After Width: | Height: | Size: 238 B |
|
After Width: | Height: | Size: 241 B |
|
After Width: | Height: | Size: 232 B |
|
After Width: | Height: | Size: 210 B |
|
After Width: | Height: | Size: 229 B |
|
After Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 241 B |
@@ -4,6 +4,7 @@
|
||||
|
||||
// window statics
|
||||
static Window *s_main_window;
|
||||
static Layer *s_window_layer;
|
||||
static BitmapLayer *s_time_mg_layers[4];
|
||||
static BitmapLayer *s_time_fg_layers[4];
|
||||
static BitmapLayer *s_c_layer;
|
||||
@@ -23,13 +24,13 @@ static const uint16_t s_fuel_guage_x_pos = PBL_DISPLAY_WIDTH - 23;
|
||||
// settings statics
|
||||
static ClaySettings settings;
|
||||
static GColor s_applied_time_mg = GColorDarkGray;
|
||||
static GColor s_applied_f = GColorWhite; // only foreground element to not change color for warnings, so it is used as the base fg color
|
||||
static GColor s_applied_e = GColorWhite;
|
||||
static GColor s_applied_e_f = GColorWhite;
|
||||
static GColor s_applied_c_h = GColorWhite;
|
||||
static GColor s_applied_time_date = GColorWhite;
|
||||
|
||||
// bitmap statics
|
||||
static GBitmap *s_font_bitmaps[10];
|
||||
static GBitmap *s_font_bitmaps_mini[10];
|
||||
static GBitmap *s_time_mg_super8;
|
||||
static GBitmap *s_c_icon;
|
||||
static GBitmap *s_h_icon;
|
||||
@@ -37,6 +38,7 @@ static GBitmap *s_e_icon;
|
||||
static GBitmap *s_f_icon;
|
||||
|
||||
// tracking statics
|
||||
static bool s_peek_active = false;
|
||||
static bool s_first_settings_application = true;
|
||||
static bool s_showing_date = false;
|
||||
static AppTimer *s_date_timer = NULL;
|
||||
@@ -56,13 +58,14 @@ static void toggle_fuel_warning_state(bool enable_warning, bool force) {
|
||||
return;
|
||||
}
|
||||
GColor dst = enable_warning ? settings.ColorWarning : settings.ColorFG;
|
||||
if (s_first_settings_application && !enable_warning && dst.argb == s_applied_e.argb) {
|
||||
if (s_first_settings_application && !enable_warning && dst.argb == s_applied_e_f.argb) {
|
||||
// at startup, s_applied_e.argb is GColorWhite
|
||||
// for those using white fg, do not pointlessly replace white at startup if that is the destination anyway
|
||||
return;
|
||||
}
|
||||
replace_gbitmap_color(s_applied_e, dst, s_e_icon, s_e_layer);
|
||||
s_applied_e = dst;
|
||||
replace_gbitmap_color(s_applied_e_f, dst, s_e_icon, s_e_layer);
|
||||
replace_gbitmap_color(s_applied_e_f, dst, s_f_icon, s_f_layer);
|
||||
s_applied_e_f = dst;
|
||||
s_fuel_is_warning = enable_warning;
|
||||
}
|
||||
|
||||
@@ -196,8 +199,15 @@ static void update_minute_1() {
|
||||
s_time_digits[2] = minute / 10;
|
||||
s_time_digits[3] = minute % 10;
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
bitmap_layer_set_bitmap(s_time_fg_layers[i], s_font_bitmaps[s_time_digits[i]]);
|
||||
if (!s_peek_active) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
bitmap_layer_set_bitmap(s_time_fg_layers[i], s_font_bitmaps[s_time_digits[i]]);
|
||||
}
|
||||
} else {
|
||||
bitmap_layer_set_bitmap(s_time_fg_layers[0], s_font_bitmaps[s_time_digits[0]]);
|
||||
bitmap_layer_set_bitmap(s_time_fg_layers[1], s_font_bitmaps[s_time_digits[1]]);
|
||||
bitmap_layer_set_bitmap(s_time_fg_layers[2], s_font_bitmaps_mini[s_time_digits[2]]);
|
||||
bitmap_layer_set_bitmap(s_time_fg_layers[3], s_font_bitmaps_mini[s_time_digits[3]]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,6 +242,38 @@ static void accel_tap_handler(AccelAxisType axis, int32_t direction) {
|
||||
s_date_timer = app_timer_register(settings.DateTimeoutSecs * 1000, date_timeout, NULL);
|
||||
}
|
||||
|
||||
static void peek_will_change(GRect final_unobstructed_screen_area, void *context) {
|
||||
// if obstructed, set s_peek_active and run update_minute_1 to use small minutes
|
||||
GRect full_bounds = layer_get_bounds(s_window_layer);
|
||||
if (!grect_equal(&full_bounds, &final_unobstructed_screen_area)) {
|
||||
s_peek_active = true;
|
||||
if (!s_showing_date) {
|
||||
update_minute_1();
|
||||
}
|
||||
} else {
|
||||
s_peek_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void peek_change(AnimationProgress progress, void *context) {
|
||||
// animate the moving of the minute layers depending on s_peek_active
|
||||
if (!s_peek_active) {
|
||||
layer_set_frame(bitmap_layer_get_layer(s_time_fg_layers[2]), s_time_grects[2]);
|
||||
layer_set_frame(bitmap_layer_get_layer(s_time_fg_layers[3]), s_time_grects[3]);
|
||||
} else {
|
||||
uint8_t y = s_time_grects[2].origin.y - 1;
|
||||
layer_set_frame(bitmap_layer_get_layer(s_time_fg_layers[2]), GRect(s_time_grects[2].origin.x, y, 69, 54));
|
||||
layer_set_frame(bitmap_layer_get_layer(s_time_fg_layers[3]), GRect(s_time_grects[3].origin.x, y, 69, 54));
|
||||
}
|
||||
}
|
||||
|
||||
static void peek_did_change(void *context) {
|
||||
// if not obstructed, run update_minute_1 to use large minutes
|
||||
if (!s_peek_active && !s_showing_date) {
|
||||
update_minute_1();
|
||||
}
|
||||
}
|
||||
|
||||
static void apply_settings() {
|
||||
// LED&BG
|
||||
if (settings.UseCustomLED) {
|
||||
@@ -251,7 +293,7 @@ static void apply_settings() {
|
||||
//// create and insert any mg layer that does not already exist
|
||||
Layer *sibling_layer = NULL;
|
||||
if (s_first_settings_application) {
|
||||
sibling_layer = window_get_root_layer(s_main_window);
|
||||
sibling_layer = s_window_layer;
|
||||
} else {
|
||||
sibling_layer = bitmap_layer_get_layer(s_time_fg_layers[0]);
|
||||
}
|
||||
@@ -308,10 +350,6 @@ static void apply_settings() {
|
||||
// fuel (e icon)
|
||||
toggle_fuel_warning_state(s_fuel_is_warning, true);
|
||||
|
||||
// f icon (always fg color, never a warning indicator)
|
||||
replace_gbitmap_color(s_applied_f, settings.ColorFG, s_f_icon, s_f_layer);
|
||||
s_applied_f = settings.ColorFG;
|
||||
|
||||
// changes to temperature range
|
||||
update_temperature();
|
||||
|
||||
@@ -324,13 +362,50 @@ static void apply_settings() {
|
||||
accel_tap_service_subscribe(accel_tap_handler);
|
||||
}
|
||||
|
||||
// re-sub timeline peek and create/destroy resources as needed
|
||||
// TODO add mg support, fix broken-ness when toggling peak support off while running
|
||||
unobstructed_area_service_unsubscribe();
|
||||
if (settings.EnablePeek) {
|
||||
if (!s_font_bitmaps_mini[0]) {
|
||||
s_font_bitmaps_mini[0] = gbitmap_create_with_resource(RESOURCE_ID_0_M);
|
||||
s_font_bitmaps_mini[1] = gbitmap_create_with_resource(RESOURCE_ID_1_M);
|
||||
s_font_bitmaps_mini[2] = gbitmap_create_with_resource(RESOURCE_ID_2_M);
|
||||
s_font_bitmaps_mini[3] = gbitmap_create_with_resource(RESOURCE_ID_3_M);
|
||||
s_font_bitmaps_mini[4] = gbitmap_create_with_resource(RESOURCE_ID_4_M);
|
||||
s_font_bitmaps_mini[5] = gbitmap_create_with_resource(RESOURCE_ID_5_M);
|
||||
s_font_bitmaps_mini[6] = gbitmap_create_with_resource(RESOURCE_ID_6_M);
|
||||
s_font_bitmaps_mini[7] = gbitmap_create_with_resource(RESOURCE_ID_7_M);
|
||||
s_font_bitmaps_mini[8] = gbitmap_create_with_resource(RESOURCE_ID_8_M);
|
||||
s_font_bitmaps_mini[9] = gbitmap_create_with_resource(RESOURCE_ID_9_M);
|
||||
}
|
||||
peek_will_change(layer_get_unobstructed_bounds(s_window_layer), NULL);
|
||||
peek_change(0, NULL);
|
||||
peek_did_change(NULL);
|
||||
UnobstructedAreaHandlers peek_handlers = {
|
||||
.will_change = peek_will_change,
|
||||
.change = peek_change,
|
||||
.did_change = peek_did_change,
|
||||
};
|
||||
unobstructed_area_service_subscribe(peek_handlers, NULL);
|
||||
} else {
|
||||
peek_will_change(layer_get_bounds(s_window_layer), NULL);
|
||||
peek_change(0, NULL);
|
||||
peek_did_change(NULL);
|
||||
if (s_font_bitmaps_mini[0]) {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
gbitmap_destroy(s_font_bitmaps_mini[i]);
|
||||
s_font_bitmaps_mini[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s_first_settings_application) {
|
||||
s_first_settings_application = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void main_window_load() {
|
||||
Layer *window_layer = window_get_root_layer(s_main_window);
|
||||
s_window_layer = window_get_root_layer(s_main_window);
|
||||
|
||||
s_temp_mg_layer = layer_create(GRect(s_temp_guage_x_pos - 1, 21, s_bar_width + 2, PBL_DISPLAY_HEIGHT - 43));
|
||||
layer_set_update_proc(s_temp_mg_layer, temp_mg_update_proc);
|
||||
@@ -353,19 +428,25 @@ static void main_window_load() {
|
||||
apply_settings();
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
layer_add_child(window_layer, bitmap_layer_get_layer(s_time_fg_layers[i]));
|
||||
layer_add_child(s_window_layer, bitmap_layer_get_layer(s_time_fg_layers[i]));
|
||||
}
|
||||
layer_add_child(window_layer, bitmap_layer_get_layer(s_c_layer));
|
||||
layer_add_child(window_layer, bitmap_layer_get_layer(s_h_layer));
|
||||
layer_add_child(window_layer, bitmap_layer_get_layer(s_e_layer));
|
||||
layer_add_child(window_layer, bitmap_layer_get_layer(s_f_layer));
|
||||
layer_add_child(window_layer, s_temp_mg_layer);
|
||||
layer_add_child(window_layer, s_temp_layer);
|
||||
layer_add_child(window_layer, s_fuel_mg_layer);
|
||||
layer_add_child(window_layer, s_fuel_layer);
|
||||
layer_add_child(s_window_layer, bitmap_layer_get_layer(s_c_layer));
|
||||
layer_add_child(s_window_layer, bitmap_layer_get_layer(s_h_layer));
|
||||
layer_add_child(s_window_layer, bitmap_layer_get_layer(s_e_layer));
|
||||
layer_add_child(s_window_layer, bitmap_layer_get_layer(s_f_layer));
|
||||
layer_add_child(s_window_layer, s_temp_mg_layer);
|
||||
layer_add_child(s_window_layer, s_temp_layer);
|
||||
layer_add_child(s_window_layer, s_fuel_mg_layer);
|
||||
layer_add_child(s_window_layer, s_fuel_layer);
|
||||
}
|
||||
|
||||
static void main_window_unload() {
|
||||
if (settings.EnablePeek) {
|
||||
unobstructed_area_service_unsubscribe();
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
gbitmap_destroy(s_font_bitmaps_mini[i]);
|
||||
}
|
||||
}
|
||||
connection_service_unsubscribe();
|
||||
accel_tap_service_unsubscribe();
|
||||
layer_destroy(s_fuel_mg_layer);
|
||||
@@ -405,6 +486,7 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) {
|
||||
}
|
||||
|
||||
// CLAY SETTINGS
|
||||
Tuple *enable_peek_tuple = dict_find(iter, MESSAGE_KEY_CLAY_ENABLE_PEEK);
|
||||
Tuple *track_bt_tuple = dict_find(iter, MESSAGE_KEY_CLAY_BT_INDICATOR);
|
||||
Tuple *show_time_mg_tuple = dict_find(iter, MESSAGE_KEY_CLAY_SHOW_TIME_MG);
|
||||
Tuple *use_custom_led_tuple = dict_find(iter, MESSAGE_KEY_CLAY_USE_CUSTOM_LED);
|
||||
@@ -418,6 +500,9 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) {
|
||||
Tuple *color_mg_time_tuple = dict_find(iter, MESSAGE_KEY_CLAY_TIME_MG_COLOR);
|
||||
Tuple *color_fg_tuple = dict_find(iter, MESSAGE_KEY_CLAY_FG_COLOR);
|
||||
Tuple *color_warning_tuple = dict_find(iter, MESSAGE_KEY_CLAY_WARNING_COLOR);
|
||||
if (enable_peek_tuple) {
|
||||
settings.EnablePeek = enable_peek_tuple->value->uint8;
|
||||
}
|
||||
if (track_bt_tuple) {
|
||||
settings.TrackBTStatus = track_bt_tuple->value->uint8;
|
||||
}
|
||||
@@ -466,6 +551,7 @@ static void init() {
|
||||
if (persist_exists(STORAGE_KEY_SETTINGS)) {
|
||||
persist_read_data(STORAGE_KEY_SETTINGS, &settings, sizeof(settings));
|
||||
} else {
|
||||
settings.EnablePeek = true;
|
||||
settings.TrackBTStatus = false;
|
||||
settings.ShowTimeMG = false;
|
||||
settings.UseCustomLED = false;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#define STORAGE_KEY_SETTINGS 69
|
||||
|
||||
typedef struct ClaySettings {
|
||||
bool EnablePeek;
|
||||
bool TrackBTStatus;
|
||||
bool ShowTimeMG;
|
||||
bool UseCustomLED;
|
||||
|
||||
@@ -11,6 +11,14 @@ module.exports = [
|
||||
"size": 3,
|
||||
"defaultValue": "Options"
|
||||
},
|
||||
{
|
||||
"id": "peek_toggle",
|
||||
"type": "toggle",
|
||||
"messageKey": "CLAY_ENABLE_PEEK",
|
||||
"defaultValue": true,
|
||||
"label": "Timeline peek/quickview support",
|
||||
"description": "Disable to reduce resource usage if NOT using timeline peek/quickview."
|
||||
},
|
||||
{
|
||||
"id": "time_mg_toggle",
|
||||
"type": "toggle",
|
||||
|
||||