Files
Civic-Segments/src/c/main.c
T

378 lines
13 KiB
C

#include "palette_manip.h"
#include "settings.h"
#include <pebble.h>
// window statics
static Window *s_main_window;
static BitmapLayer *s_time_mg_layers[4];
static BitmapLayer *s_time_fg_layers[4];
static BitmapLayer *s_c_layer;
static BitmapLayer *s_h_layer;
static BitmapLayer *s_e_layer;
static BitmapLayer *s_f_layer;
static Layer *s_temp_mg_layer;
static Layer *s_temp_layer;
static Layer *s_fuel_mg_layer;
static Layer *s_fuel_layer;
static const uint8_t s_x_r = (PBL_DISPLAY_WIDTH / 2) + 2;
static const uint8_t s_x_l = (s_x_r - 2 * (69 / 2)) - 5;
#if PBL_DISPLAY_HEIGHT == 260
static const GRect s_time_grects[4] = {GRect(s_x_l, 18, 69, 110), GRect(s_x_r, 18, 69, 110), GRect(s_x_l, 132, 69, 110), GRect(s_x_r, 132, 69, 110)};
#elif PBL_DISPLAY_HEIGHT == 180
static const GRect s_time_grects[4] = {GRect(s_x_l, -22, 69, 110), GRect(s_x_r, -22, 69, 110), GRect(s_x_l, 92, 69, 110), GRect(s_x_r, 92, 69, 110)};
#else
static const GRect s_time_grects[4] = {GRect(s_x_l, 2, 69, 110), GRect(s_x_r, 2, 69, 110), GRect(s_x_l, 116, 69, 110), GRect(s_x_r, 116, 69, 110)};
#endif
static const uint8_t s_temp_guage_x_pos = 6;
static const uint16_t s_fuel_guage_x_pos = PBL_DISPLAY_WIDTH - 23;
// settings statics
static ClaySettings settings;
static GColor s_applied_fg = GColorWhite;
static GColor s_applied_time_mg = GColorWhite;
// bitmap statics
static GBitmap *s_font_bitmaps[10];
static GBitmap *s_time_mg_super8;
static GBitmap *s_c_icon;
static GBitmap *s_h_icon;
static GBitmap *s_e_icon;
static GBitmap *s_f_icon;
// tracking statics
static int s_batt_level;
// bar statics
static const uint8_t s_bar_height = 8;
static const uint8_t s_bar_width = 17;
static const uint8_t s_bar_spacing = s_bar_height + 1;
static void batt_callback(BatteryChargeState state) {
s_batt_level = state.charge_percent;
layer_mark_dirty(s_fuel_layer);
layer_mark_dirty(s_temp_layer); // TODO temporary!!
}
// TODO use temperature (for now it updates with battery usage)
static void temp_update_proc(Layer *layer, GContext *ctx) {
graphics_context_set_fill_color(ctx, GColorWhite);
const uint8_t bar_count = s_batt_level / 5;
uint16_t bar_bottom_pos = 195;
for (uint8_t i = 0; i < bar_count; ++i) {
graphics_fill_rect(ctx, GRect(0, bar_bottom_pos, s_bar_width, s_bar_height), 0, GCornerNone);
bar_bottom_pos -= s_bar_spacing;
}
}
static void fuel_update_proc(Layer *layer, GContext *ctx) {
graphics_context_set_fill_color(ctx, GColorWhite);
const uint8_t bar_count = s_batt_level / 5;
uint16_t bar_bottom_pos = 195;
for (uint8_t i = 0; i < bar_count; ++i) {
graphics_fill_rect(ctx, GRect(0, bar_bottom_pos, s_bar_width, s_bar_height), 0, GCornerNone);
bar_bottom_pos -= s_bar_spacing;
}
}
static void temp_fuel_mg_update_proc_helper(Layer *layer, GContext *ctx, bool isFuel) {
GRect bounds = layer_get_bounds(layer);
graphics_context_set_fill_color(ctx, settings.ColorMGBars);
graphics_fill_rect(ctx, bounds, 0, GCornerNone);
if (isFuel) {
graphics_context_set_stroke_color(ctx, GColorRed);
} else {
graphics_context_set_stroke_color(ctx, GColorDukeBlue);
}
const uint16_t bottom_color_y = bounds.origin.y + 183;
graphics_draw_line(ctx, GPoint(bounds.origin.x + 1, bottom_color_y), GPoint(bounds.origin.x + s_bar_width, bottom_color_y));
if (isFuel) {
graphics_context_set_stroke_color(ctx, GColorDukeBlue);
} else {
graphics_context_set_stroke_color(ctx, GColorRed);
}
const uint16_t top_color_y = bounds.origin.y + 1;
graphics_draw_line(ctx, GPoint(bounds.origin.x + 1, top_color_y), GPoint(bounds.origin.x + s_bar_width, top_color_y));
}
static void temp_mg_update_proc(Layer *layer, GContext *ctx) {
temp_fuel_mg_update_proc_helper(layer, ctx, false);
}
static void fuel_mg_update_proc(Layer *layer, GContext *ctx) {
temp_fuel_mg_update_proc_helper(layer, ctx, true);
}
static void apply_settings(bool first_run) {
// LED&BG
light_set_color(settings.ColorLED); // no-op on unsupported platforms
window_set_background_color(s_main_window, settings.ColorBG);
// TIME MG
if (settings.ShowTimeMG) {
//// load bitmap if not already loaded
if (!s_time_mg_super8) {
s_time_mg_super8 = gbitmap_create_with_resource(RESOURCE_ID_SUPER8);
s_applied_time_mg = GColorWhite;
}
//// create and insert any mg layer that does not already exist
Layer *sibling_layer = NULL;
if (first_run) {
sibling_layer = window_get_root_layer(s_main_window);
} else {
sibling_layer = bitmap_layer_get_layer(s_time_fg_layers[0]);
}
for (int i = 0; i < 4; ++i) {
if (!s_time_mg_layers[i]) {
s_time_mg_layers[i] = bitmap_layer_create(s_time_grects[i]);
bitmap_layer_set_bitmap(s_time_mg_layers[i], s_time_mg_super8);
bitmap_layer_set_compositing_mode(s_time_mg_layers[i], GCompOpSet);
if (first_run) {
layer_add_child(sibling_layer, bitmap_layer_get_layer(s_time_mg_layers[i]));
} else {
layer_insert_below_sibling(bitmap_layer_get_layer(s_time_mg_layers[i]), sibling_layer);
}
}
}
//// set bitmap color and mark layers dirty
if (s_time_mg_super8 && settings.ColorMGTime.argb != s_applied_time_mg.argb) {
replace_gbitmap_color(s_applied_time_mg, settings.ColorMGTime, s_time_mg_super8, NULL);
for (int i = 0; i < 4; ++i) {
if (s_time_mg_layers[i]) {
layer_mark_dirty(bitmap_layer_get_layer(s_time_mg_layers[i]));
}
}
s_applied_time_mg = settings.ColorMGTime;
}
} else {
if (s_time_mg_super8) {
for (int i = 0; i < 4; ++i) {
bitmap_layer_destroy(s_time_mg_layers[i]);
s_time_mg_layers[i] = NULL;
}
gbitmap_destroy(s_time_mg_super8);
s_time_mg_super8 = NULL;
}
}
// BAR MG
layer_mark_dirty(s_temp_mg_layer);
layer_mark_dirty(s_fuel_mg_layer);
// FG
if (settings.ColorFG.argb != s_applied_fg.argb) {
for (int i = 0; i < 10; ++i) {
replace_gbitmap_color(s_applied_fg, settings.ColorFG, s_font_bitmaps[i], NULL);
}
for (int i = 0; i < 4; ++i) {
layer_mark_dirty(bitmap_layer_get_layer(s_time_fg_layers[i]));
}
replace_gbitmap_color(s_applied_fg, settings.ColorFG, s_c_icon, s_c_layer);
replace_gbitmap_color(s_applied_fg, settings.ColorFG, s_h_icon, s_h_layer);
replace_gbitmap_color(s_applied_fg, settings.ColorFG, s_e_icon, s_e_layer);
replace_gbitmap_color(s_applied_fg, settings.ColorFG, s_f_icon, s_f_layer);
s_applied_fg = settings.ColorFG;
}
}
static void main_window_load() {
Layer *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);
s_fuel_mg_layer = layer_create(GRect(s_fuel_guage_x_pos - 1, 21, s_bar_width + 2, PBL_DISPLAY_HEIGHT - 43));
layer_set_update_proc(s_fuel_mg_layer, fuel_mg_update_proc);
s_c_layer = bitmap_layer_create(GRect(s_temp_guage_x_pos, PBL_DISPLAY_HEIGHT - 18, 17, 15));
s_h_layer = bitmap_layer_create(GRect(s_temp_guage_x_pos, 3, 17, 14));
s_e_layer = bitmap_layer_create(GRect(s_fuel_guage_x_pos, PBL_DISPLAY_HEIGHT - 18, 17, 15));
s_f_layer = bitmap_layer_create(GRect(s_fuel_guage_x_pos, 3, 17, 14));
bitmap_layer_set_bitmap(s_c_layer, s_c_icon);
bitmap_layer_set_bitmap(s_h_layer, s_h_icon);
bitmap_layer_set_bitmap(s_e_layer, s_e_icon);
bitmap_layer_set_bitmap(s_f_layer, s_f_icon);
bitmap_layer_set_compositing_mode(s_c_layer, GCompOpSet);
bitmap_layer_set_compositing_mode(s_h_layer, GCompOpSet);
bitmap_layer_set_compositing_mode(s_e_layer, GCompOpSet);
bitmap_layer_set_compositing_mode(s_f_layer, GCompOpSet);
apply_settings(true);
for (int i = 0; i < 4; ++i) {
layer_add_child(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);
}
static void main_window_unload() {
layer_destroy(s_fuel_mg_layer);
layer_destroy(s_temp_mg_layer);
bitmap_layer_destroy(s_f_layer);
bitmap_layer_destroy(s_e_layer);
bitmap_layer_destroy(s_h_layer);
bitmap_layer_destroy(s_c_layer);
if (s_time_mg_super8) {
gbitmap_destroy(s_time_mg_super8);
for (int i = 0; i < 4; ++i) {
bitmap_layer_destroy(s_time_mg_layers[i]);
}
}
}
static void update_minute_1() {
time_t temp = time(NULL);
struct tm *tick_time = localtime(&temp);
uint8_t hour = (uint8_t)tick_time->tm_hour;
if (!clock_is_24h_style()) {
hour = hour % 12;
if (hour == 0) {
hour = 12;
}
}
uint8_t minute = (uint8_t)tick_time->tm_min;
static uint8_t s_time_digits[4];
s_time_digits[0] = hour / 10;
s_time_digits[1] = hour % 10;
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]]);
}
}
static void minute_handler(struct tm *tick_time, TimeUnits units_changed) {
update_minute_1();
}
static void inbox_received_handler(DictionaryIterator *iter, void *context) {
Tuple *ready_tuple = dict_find(iter, MESSAGE_KEY_PKJS_READY);
if (ready_tuple) {
// TODO request temp bars from PKJS
return;
}
// TEMPERATURE DATA
Tuple *temp_bar_count = dict_find(iter, MESSAGE_KEY_PKJS_TEMP_BAR_COUNT);
if (temp_bar_count) {
// TODO
return;
}
// CLAY SETTINGS
Tuple *show_time_mg_tuple = dict_find(iter, MESSAGE_KEY_CLAY_SHOW_TIME_MG);
Tuple *color_led_tuple = dict_find(iter, MESSAGE_KEY_CLAY_LED_COLOR);
Tuple *color_bg_tuple = dict_find(iter, MESSAGE_KEY_CLAY_BG_COLOR);
Tuple *color_mg_bar_tuple = dict_find(iter, MESSAGE_KEY_CLAY_BAR_MG_COLOR);
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);
if (show_time_mg_tuple) {
settings.ShowTimeMG = show_time_mg_tuple->value->uint8;
}
if (color_led_tuple) {
settings.ColorLED = GColorFromHEX(color_led_tuple->value->int32);
}
if (color_bg_tuple) {
settings.ColorBG = GColorFromHEX(color_bg_tuple->value->int32);
}
if (color_mg_bar_tuple) {
settings.ColorMGBars = GColorFromHEX(color_mg_bar_tuple->value->int32);
}
if (color_mg_time_tuple) {
settings.ColorMGTime = GColorFromHEX(color_mg_time_tuple->value->int32);
}
if (color_fg_tuple) {
settings.ColorFG = GColorFromHEX(color_fg_tuple->value->int32);
}
persist_write_data(STORAGE_KEY_SETTINGS, &settings, sizeof(settings));
apply_settings(false);
}
static void init() {
// load settings from persist (or set defaults if not present)
if (persist_exists(STORAGE_KEY_SETTINGS)) {
persist_read_data(STORAGE_KEY_SETTINGS, &settings, sizeof(settings));
} else {
settings.ShowTimeMG = false;
settings.ColorLED = GColorWhite;
settings.ColorBG = GColorBlue;
settings.ColorMGBars = GColorDarkGray;
settings.ColorMGTime = GColorDarkGray;
settings.ColorFG = GColorWhite;
}
// load bitmaps
s_font_bitmaps[0] = gbitmap_create_with_resource(RESOURCE_ID_0);
s_font_bitmaps[1] = gbitmap_create_with_resource(RESOURCE_ID_1);
s_font_bitmaps[2] = gbitmap_create_with_resource(RESOURCE_ID_2);
s_font_bitmaps[3] = gbitmap_create_with_resource(RESOURCE_ID_3);
s_font_bitmaps[4] = gbitmap_create_with_resource(RESOURCE_ID_4);
s_font_bitmaps[5] = gbitmap_create_with_resource(RESOURCE_ID_5);
s_font_bitmaps[6] = gbitmap_create_with_resource(RESOURCE_ID_6);
s_font_bitmaps[7] = gbitmap_create_with_resource(RESOURCE_ID_7);
s_font_bitmaps[8] = gbitmap_create_with_resource(RESOURCE_ID_8);
s_font_bitmaps[9] = gbitmap_create_with_resource(RESOURCE_ID_9);
s_c_icon = gbitmap_create_with_resource(RESOURCE_ID_C);
s_h_icon = gbitmap_create_with_resource(RESOURCE_ID_H);
s_e_icon = gbitmap_create_with_resource(RESOURCE_ID_E);
s_f_icon = gbitmap_create_with_resource(RESOURCE_ID_F);
for (int i = 0; i < 4; ++i) {
s_time_fg_layers[i] = bitmap_layer_create(s_time_grects[i]);
bitmap_layer_set_compositing_mode(s_time_fg_layers[i], GCompOpSet);
}
s_temp_layer = layer_create(GRect(s_temp_guage_x_pos, 0, s_bar_width, PBL_DISPLAY_HEIGHT));
layer_set_update_proc(s_temp_layer, temp_update_proc);
s_fuel_layer = layer_create(GRect(s_fuel_guage_x_pos, 0, s_bar_width, PBL_DISPLAY_HEIGHT));
layer_set_update_proc(s_fuel_layer, fuel_update_proc);
update_minute_1();
batt_callback(battery_state_service_peek());
app_message_register_inbox_received(inbox_received_handler);
app_message_open(255, 64);
s_main_window = window_create();
window_set_window_handlers(
s_main_window,
(WindowHandlers){.load = main_window_load, .unload = main_window_unload});
window_stack_push(s_main_window, false);
tick_timer_service_subscribe(MINUTE_UNIT, minute_handler);
battery_state_service_subscribe(batt_callback);
}
static void deinit() {
battery_state_service_unsubscribe();
tick_timer_service_unsubscribe();
layer_destroy(s_fuel_layer);
layer_destroy(s_temp_layer);
gbitmap_destroy(s_f_icon);
gbitmap_destroy(s_e_icon);
gbitmap_destroy(s_h_icon);
gbitmap_destroy(s_c_icon);
for (int i = 0; i < 4; ++i) {
bitmap_layer_destroy(s_time_fg_layers[i]);
}
for (int i = 0; i < 10; ++i) {
gbitmap_destroy(s_font_bitmaps[i]);
}
window_destroy(s_main_window);
}
int main(void) {
init();
app_event_loop();
deinit();
}