From 061391f78af8c88febadfacdf16bf62e76bf5a54 Mon Sep 17 00:00:00 2001 From: Ari Wilson Date: Mon, 2 Jun 2014 00:33:49 -0700 Subject: [PATCH] Add HTML settings menu instead of precompiled constants. --- appinfo.json | 422 ++++++++++++++++++++-------------------- index.html | 79 ++++++++ src/Revolution.c | 156 ++++++++++----- src/js/pebble-js-app.js | 16 ++ 4 files changed, 416 insertions(+), 257 deletions(-) create mode 100644 index.html create mode 100644 src/js/pebble-js-app.js diff --git a/appinfo.json b/appinfo.json index 879c2dd..337cee9 100644 --- a/appinfo.json +++ b/appinfo.json @@ -1,211 +1,215 @@ { - "uuid": "a1230861-d4eb-4f6e-a2d0-eaa2a07797dd", - "shortName": "Revolution", - "longName": "Revolution", - "companyName": "Douwe Maan", - "versionCode": 201, - "versionLabel": "2.0.1", - "watchapp": { - "watchface": true - }, - "appKeys": {}, - "resources": { - "media": [ - { - "menuIcon": true, - "type": "png", - "name": "IMAGE_MENU_ICON", - "file": "images/menu_icon.png" - }, - - { - "type": "png", - "name": "IMAGE_TIME_0", - "file": "images/time_0.png" - }, - { - "type": "png", - "name": "IMAGE_TIME_1", - "file": "images/time_1.png" - }, - { - "type": "png", - "name": "IMAGE_TIME_2", - "file": "images/time_2.png" - }, - { - "type": "png", - "name": "IMAGE_TIME_3", - "file": "images/time_3.png" - }, - { - "type": "png", - "name": "IMAGE_TIME_4", - "file": "images/time_4.png" - }, - { - "type": "png", - "name": "IMAGE_TIME_5", - "file": "images/time_5.png" - }, - { - "type": "png", - "name": "IMAGE_TIME_6", - "file": "images/time_6.png" - }, - { - "type": "png", - "name": "IMAGE_TIME_7", - "file": "images/time_7.png" - }, - { - "type": "png", - "name": "IMAGE_TIME_8", - "file": "images/time_8.png" - }, - { - "type": "png", - "name": "IMAGE_TIME_9", - "file": "images/time_9.png" - }, - - { - "type": "png", - "name": "IMAGE_DATE_0", - "file": "images/date_0.png" - }, - { - "type": "png", - "name": "IMAGE_DATE_1", - "file": "images/date_1.png" - }, - { - "type": "png", - "name": "IMAGE_DATE_2", - "file": "images/date_2.png" - }, - { - "type": "png", - "name": "IMAGE_DATE_3", - "file": "images/date_3.png" - }, - { - "type": "png", - "name": "IMAGE_DATE_4", - "file": "images/date_4.png" - }, - { - "type": "png", - "name": "IMAGE_DATE_5", - "file": "images/date_5.png" - }, - { - "type": "png", - "name": "IMAGE_DATE_6", - "file": "images/date_6.png" - }, - { - "type": "png", - "name": "IMAGE_DATE_7", - "file": "images/date_7.png" - }, - { - "type": "png", - "name": "IMAGE_DATE_8", - "file": "images/date_8.png" - }, - { - "type": "png", - "name": "IMAGE_DATE_9", - "file": "images/date_9.png" - }, - - { - "type": "png", - "name": "IMAGE_SECOND_0", - "file": "images/second_0.png" - }, - { - "type": "png", - "name": "IMAGE_SECOND_1", - "file": "images/second_1.png" - }, - { - "type": "png", - "name": "IMAGE_SECOND_2", - "file": "images/second_2.png" - }, - { - "type": "png", - "name": "IMAGE_SECOND_3", - "file": "images/second_3.png" - }, - { - "type": "png", - "name": "IMAGE_SECOND_4", - "file": "images/second_4.png" - }, - { - "type": "png", - "name": "IMAGE_SECOND_5", - "file": "images/second_5.png" - }, - { - "type": "png", - "name": "IMAGE_SECOND_6", - "file": "images/second_6.png" - }, - { - "type": "png", - "name": "IMAGE_SECOND_7", - "file": "images/second_7.png" - }, - { - "type": "png", - "name": "IMAGE_SECOND_8", - "file": "images/second_8.png" - }, - { - "type": "png", - "name": "IMAGE_SECOND_9", - "file": "images/second_9.png" - }, - - { - "type": "png", - "name": "IMAGE_DAY_0", - "file": "images/day_0.png" - }, - { - "type": "png", - "name": "IMAGE_DAY_1", - "file": "images/day_1.png" - }, - { - "type": "png", - "name": "IMAGE_DAY_2", - "file": "images/day_2.png" - }, - { - "type": "png", - "name": "IMAGE_DAY_3", - "file": "images/day_3.png" - }, - { - "type": "png", - "name": "IMAGE_DAY_4", - "file": "images/day_4.png" - }, - { - "type": "png", - "name": "IMAGE_DAY_5", - "file": "images/day_5.png" - }, - { - "type": "png", - "name": "IMAGE_DAY_6", - "file": "images/day_6.png" - } - ] - } + "longName": "Revolution", + "versionLabel": "2.0.1", + "companyName": "Douwe Maan", + "appKeys": { + "display_year": 3, + "use_american_date_format": 0, + "vibe_on_hour": 1, + "invert_colors": 2 + }, + "capabilities": [ + "configurable" + ], + "uuid": "a1230861-d4eb-4f6e-a2d0-eaa2a07797dd", + "watchapp": { + "watchface": true + }, + "shortName": "Revolution", + "versionCode": 201, + "resources": { + "media": [ + { + "file": "images/menu_icon.png", + "menuIcon": true, + "name": "IMAGE_MENU_ICON", + "type": "png" + }, + { + "file": "images/time_0.png", + "name": "IMAGE_TIME_0", + "type": "png" + }, + { + "file": "images/time_1.png", + "name": "IMAGE_TIME_1", + "type": "png" + }, + { + "file": "images/time_2.png", + "name": "IMAGE_TIME_2", + "type": "png" + }, + { + "file": "images/time_3.png", + "name": "IMAGE_TIME_3", + "type": "png" + }, + { + "file": "images/time_4.png", + "name": "IMAGE_TIME_4", + "type": "png" + }, + { + "file": "images/time_5.png", + "name": "IMAGE_TIME_5", + "type": "png" + }, + { + "file": "images/time_6.png", + "name": "IMAGE_TIME_6", + "type": "png" + }, + { + "file": "images/time_7.png", + "name": "IMAGE_TIME_7", + "type": "png" + }, + { + "file": "images/time_8.png", + "name": "IMAGE_TIME_8", + "type": "png" + }, + { + "file": "images/time_9.png", + "name": "IMAGE_TIME_9", + "type": "png" + }, + { + "file": "images/date_0.png", + "name": "IMAGE_DATE_0", + "type": "png" + }, + { + "file": "images/date_1.png", + "name": "IMAGE_DATE_1", + "type": "png" + }, + { + "file": "images/date_2.png", + "name": "IMAGE_DATE_2", + "type": "png" + }, + { + "file": "images/date_3.png", + "name": "IMAGE_DATE_3", + "type": "png" + }, + { + "file": "images/date_4.png", + "name": "IMAGE_DATE_4", + "type": "png" + }, + { + "file": "images/date_5.png", + "name": "IMAGE_DATE_5", + "type": "png" + }, + { + "file": "images/date_6.png", + "name": "IMAGE_DATE_6", + "type": "png" + }, + { + "file": "images/date_7.png", + "name": "IMAGE_DATE_7", + "type": "png" + }, + { + "file": "images/date_8.png", + "name": "IMAGE_DATE_8", + "type": "png" + }, + { + "file": "images/date_9.png", + "name": "IMAGE_DATE_9", + "type": "png" + }, + { + "file": "images/second_0.png", + "name": "IMAGE_SECOND_0", + "type": "png" + }, + { + "file": "images/second_1.png", + "name": "IMAGE_SECOND_1", + "type": "png" + }, + { + "file": "images/second_2.png", + "name": "IMAGE_SECOND_2", + "type": "png" + }, + { + "file": "images/second_3.png", + "name": "IMAGE_SECOND_3", + "type": "png" + }, + { + "file": "images/second_4.png", + "name": "IMAGE_SECOND_4", + "type": "png" + }, + { + "file": "images/second_5.png", + "name": "IMAGE_SECOND_5", + "type": "png" + }, + { + "file": "images/second_6.png", + "name": "IMAGE_SECOND_6", + "type": "png" + }, + { + "file": "images/second_7.png", + "name": "IMAGE_SECOND_7", + "type": "png" + }, + { + "file": "images/second_8.png", + "name": "IMAGE_SECOND_8", + "type": "png" + }, + { + "file": "images/second_9.png", + "name": "IMAGE_SECOND_9", + "type": "png" + }, + { + "file": "images/day_0.png", + "name": "IMAGE_DAY_0", + "type": "png" + }, + { + "file": "images/day_1.png", + "name": "IMAGE_DAY_1", + "type": "png" + }, + { + "file": "images/day_2.png", + "name": "IMAGE_DAY_2", + "type": "png" + }, + { + "file": "images/day_3.png", + "name": "IMAGE_DAY_3", + "type": "png" + }, + { + "file": "images/day_4.png", + "name": "IMAGE_DAY_4", + "type": "png" + }, + { + "file": "images/day_5.png", + "name": "IMAGE_DAY_5", + "type": "png" + }, + { + "file": "images/day_6.png", + "name": "IMAGE_DAY_6", + "type": "png" + } + ] + } } diff --git a/index.html b/index.html new file mode 100644 index 0000000..7832037 --- /dev/null +++ b/index.html @@ -0,0 +1,79 @@ + + + + Configuration + + + + + + + + +
+
+

Revolution

+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+
+
+
+ + + diff --git a/src/Revolution.c b/src/Revolution.c index c37f705..a4a1a99 100644 --- a/src/Revolution.c +++ b/src/Revolution.c @@ -6,10 +6,15 @@ #include +typedef struct { + bool use_american_date_format; + bool vibe_on_hour; + bool invert_colors; + bool display_year; +} Settings; +Settings settings; // Settings -#define USE_AMERICAN_DATE_FORMAT false -#define VIBE_ON_HOUR false #define TIME_SLOT_ANIMATION_DURATION 500 // Magic numbers @@ -36,32 +41,32 @@ // Images #define NUMBER_OF_TIME_IMAGES 10 const int TIME_IMAGE_RESOURCE_IDS[NUMBER_OF_TIME_IMAGES] = { - RESOURCE_ID_IMAGE_TIME_0, - RESOURCE_ID_IMAGE_TIME_1, RESOURCE_ID_IMAGE_TIME_2, RESOURCE_ID_IMAGE_TIME_3, - RESOURCE_ID_IMAGE_TIME_4, RESOURCE_ID_IMAGE_TIME_5, RESOURCE_ID_IMAGE_TIME_6, + RESOURCE_ID_IMAGE_TIME_0, + RESOURCE_ID_IMAGE_TIME_1, RESOURCE_ID_IMAGE_TIME_2, RESOURCE_ID_IMAGE_TIME_3, + RESOURCE_ID_IMAGE_TIME_4, RESOURCE_ID_IMAGE_TIME_5, RESOURCE_ID_IMAGE_TIME_6, RESOURCE_ID_IMAGE_TIME_7, RESOURCE_ID_IMAGE_TIME_8, RESOURCE_ID_IMAGE_TIME_9 }; #define NUMBER_OF_DATE_IMAGES 10 const int DATE_IMAGE_RESOURCE_IDS[NUMBER_OF_DATE_IMAGES] = { - RESOURCE_ID_IMAGE_DATE_0, - RESOURCE_ID_IMAGE_DATE_1, RESOURCE_ID_IMAGE_DATE_2, RESOURCE_ID_IMAGE_DATE_3, - RESOURCE_ID_IMAGE_DATE_4, RESOURCE_ID_IMAGE_DATE_5, RESOURCE_ID_IMAGE_DATE_6, + RESOURCE_ID_IMAGE_DATE_0, + RESOURCE_ID_IMAGE_DATE_1, RESOURCE_ID_IMAGE_DATE_2, RESOURCE_ID_IMAGE_DATE_3, + RESOURCE_ID_IMAGE_DATE_4, RESOURCE_ID_IMAGE_DATE_5, RESOURCE_ID_IMAGE_DATE_6, RESOURCE_ID_IMAGE_DATE_7, RESOURCE_ID_IMAGE_DATE_8, RESOURCE_ID_IMAGE_DATE_9 }; #define NUMBER_OF_SECOND_IMAGES 10 const int SECOND_IMAGE_RESOURCE_IDS[NUMBER_OF_SECOND_IMAGES] = { - RESOURCE_ID_IMAGE_SECOND_0, - RESOURCE_ID_IMAGE_SECOND_1, RESOURCE_ID_IMAGE_SECOND_2, RESOURCE_ID_IMAGE_SECOND_3, - RESOURCE_ID_IMAGE_SECOND_4, RESOURCE_ID_IMAGE_SECOND_5, RESOURCE_ID_IMAGE_SECOND_6, + RESOURCE_ID_IMAGE_SECOND_0, + RESOURCE_ID_IMAGE_SECOND_1, RESOURCE_ID_IMAGE_SECOND_2, RESOURCE_ID_IMAGE_SECOND_3, + RESOURCE_ID_IMAGE_SECOND_4, RESOURCE_ID_IMAGE_SECOND_5, RESOURCE_ID_IMAGE_SECOND_6, RESOURCE_ID_IMAGE_SECOND_7, RESOURCE_ID_IMAGE_SECOND_8, RESOURCE_ID_IMAGE_SECOND_9 }; #define NUMBER_OF_DAY_IMAGES 7 const int DAY_IMAGE_RESOURCE_IDS[NUMBER_OF_DAY_IMAGES] = { - RESOURCE_ID_IMAGE_DAY_0, RESOURCE_ID_IMAGE_DAY_1, RESOURCE_ID_IMAGE_DAY_2, - RESOURCE_ID_IMAGE_DAY_3, RESOURCE_ID_IMAGE_DAY_4, RESOURCE_ID_IMAGE_DAY_5, + RESOURCE_ID_IMAGE_DAY_0, RESOURCE_ID_IMAGE_DAY_1, RESOURCE_ID_IMAGE_DAY_2, + RESOURCE_ID_IMAGE_DAY_3, RESOURCE_ID_IMAGE_DAY_4, RESOURCE_ID_IMAGE_DAY_5, RESOURCE_ID_IMAGE_DAY_6 }; @@ -138,14 +143,17 @@ void display_date(struct tm *tick_time); void display_date_value(int value, int part_number); void update_date_slot(Slot *date_slot, int digit_value); -// Seconds -void display_seconds(struct tm *tick_time); +// Seconds / years +void display_seconds_years(struct tm *tick_time); void update_second_slot(Slot *second_slot, int digit_value); +// Settings +void received_settings(DictionaryIterator* received, void* context); + // Handlers int main(void); void init(); -void handle_second_tick(struct tm *tick_time, TimeUnits units_changed); +void handle_tick(struct tm *tick_time, TimeUnits units_changed); void deinit(); @@ -174,6 +182,9 @@ BitmapLayer *load_digit_image_into_slot(Slot *slot, int digit_value, Layer *pare slot->image = gbitmap_create_with_resource(digit_resource_ids[digit_value]); slot->image_layer = bitmap_layer_create(frame); + if (settings.invert_colors) + bitmap_layer_set_compositing_mode( + slot->image_layer, GCompOpAssignInverted); bitmap_layer_set_bitmap(slot->image_layer, slot->image); layer_add_child(parent_layer, bitmap_layer_get_layer(slot->image_layer)); @@ -354,6 +365,9 @@ void display_day(struct tm *tick_time) { day_item.image = gbitmap_create_with_resource(DAY_IMAGE_RESOURCE_IDS[tick_time->tm_wday]); day_item.image_layer = bitmap_layer_create(day_item.image->bounds); + if (settings.invert_colors) + bitmap_layer_set_compositing_mode( + day_item.image_layer, GCompOpAssignInverted); bitmap_layer_set_bitmap(day_item.image_layer, day_item.image); layer_add_child(day_item.layer, bitmap_layer_get_layer(day_item.image_layer)); @@ -361,7 +375,7 @@ void display_day(struct tm *tick_time) { } void unload_day_item() { - if (!day_item.loaded) + if (!day_item.loaded) return; layer_remove_from_parent(bitmap_layer_get_layer(day_item.image_layer)); @@ -375,13 +389,13 @@ void display_date(struct tm *tick_time) { int day = tick_time->tm_mday; int month = tick_time->tm_mon + 1; -#if USE_AMERICAN_DATE_FORMAT - display_date_value(month, 0); - display_date_value(day, 1); -#else - display_date_value(day, 0); - display_date_value(month, 1); -#endif + if (settings.use_american_date_format) { + display_date_value(month, 0); + display_date_value(day, 1); + } else { + display_date_value(day, 0); + display_date_value(month, 1); + } } void display_date_value(int value, int part_number) { @@ -412,9 +426,14 @@ void update_date_slot(Slot *date_slot, int digit_value) { load_digit_image_into_slot(date_slot, digit_value, date_layer, frame, DATE_IMAGE_RESOURCE_IDS); } -// Seconds -void display_seconds(struct tm *tick_time) { - int seconds = tick_time->tm_sec; +// Seconds / years +void display_seconds_years(struct tm *tick_time) { + int seconds; + if (settings.display_year) { + seconds = tick_time->tm_year - 100; + } else { + seconds = tick_time->tm_sec; + } seconds = seconds % 100; // Maximum of two digits per row. @@ -422,7 +441,7 @@ void display_seconds(struct tm *tick_time) { Slot *second_slot = &second_slots[second_slot_number]; update_second_slot(second_slot, seconds % 10); - + seconds = seconds / 10; } } @@ -432,9 +451,9 @@ void update_second_slot(Slot *second_slot, int digit_value) { return; GRect frame = GRect( - second_slot->number * (SECOND_IMAGE_WIDTH + MARGIN), - 0, - SECOND_IMAGE_WIDTH, + second_slot->number * (SECOND_IMAGE_WIDTH + MARGIN), + 0, + SECOND_IMAGE_WIDTH, SECOND_IMAGE_HEIGHT ); @@ -442,6 +461,26 @@ void update_second_slot(Slot *second_slot, int digit_value) { load_digit_image_into_slot(second_slot, digit_value, seconds_layer, frame, SECOND_IMAGE_RESOURCE_IDS); } +void received_settings(DictionaryIterator* received, void* context) { + for (Tuple* tuple = dict_read_first(received); tuple != NULL; + tuple = dict_read_next(received)) { + switch (tuple->key) { + case 0: + settings.use_american_date_format = tuple->value->int32 == 1; + break; + case 1: + settings.vibe_on_hour = tuple->value->int32 == 1; + break; + case 2: + settings.invert_colors = tuple->value->int32 == 1; + break; + case 3: + settings.display_year = tuple->value->int32 == 1; + break; + } + } +} + // Handlers int main(void) { init(); @@ -450,9 +489,17 @@ int main(void) { } void init() { + if (persist_read_data(0, &settings, sizeof(Settings)) == E_DOES_NOT_EXIST) { + settings.use_american_date_format = false; + settings.vibe_on_hour = false; + settings.invert_colors = false; + settings.display_year = false; + } + window = window_create(); window_stack_push(window, true /* Animated */); - window_set_background_color(window, GColorBlack); + window_set_background_color( + window, (settings.invert_colors? GColorWhite : GColorBlack)); Layer *root_layer = window_get_root_layer(window); @@ -479,9 +526,9 @@ void init() { day_item.loaded = false; GRect day_layer_frame = GRect( - MARGIN, - footer_height - DAY_IMAGE_HEIGHT - MARGIN, - DAY_IMAGE_WIDTH, + MARGIN, + footer_height - DAY_IMAGE_HEIGHT - MARGIN, + DAY_IMAGE_WIDTH, DAY_IMAGE_HEIGHT ); day_item.layer = layer_create(day_layer_frame); @@ -503,7 +550,7 @@ void init() { date_layer = layer_create(date_layer_frame); layer_add_child(footer_layer, date_layer); - // Seconds + // Seconds / years for (int i = 0; i < NUMBER_OF_SECOND_SLOTS; i++) { Slot *second_slot = &second_slots[i]; second_slot->number = i; @@ -511,9 +558,9 @@ void init() { } GRect seconds_layer_frame = GRect( - SCREEN_WIDTH - SECOND_IMAGE_WIDTH - MARGIN - SECOND_IMAGE_WIDTH - MARGIN, - footer_height - SECOND_IMAGE_HEIGHT - MARGIN, - SECOND_IMAGE_WIDTH + MARGIN + SECOND_IMAGE_WIDTH, + SCREEN_WIDTH - SECOND_IMAGE_WIDTH - MARGIN - SECOND_IMAGE_WIDTH - MARGIN, + footer_height - SECOND_IMAGE_HEIGHT - MARGIN, + SECOND_IMAGE_WIDTH + MARGIN + SECOND_IMAGE_WIDTH, SECOND_IMAGE_HEIGHT ); seconds_layer = layer_create(seconds_layer_frame); @@ -526,31 +573,45 @@ void init() { display_time(tick_time); display_day(tick_time); display_date(tick_time); - display_seconds(tick_time); + display_seconds_years(tick_time); - tick_timer_service_subscribe(SECOND_UNIT, handle_second_tick); + TimeUnits tick_subscribe_interval = + (settings.display_year? MINUTE_UNIT: SECOND_UNIT); + tick_timer_service_subscribe(tick_subscribe_interval, handle_tick); + + + // Settings + app_message_register_inbox_received(received_settings); + app_message_open(256, 0); } -void handle_second_tick(struct tm *tick_time, TimeUnits units_changed) { - display_seconds(tick_time); +void handle_tick(struct tm *tick_time, TimeUnits units_changed) { + if (!settings.display_year) { + display_seconds_years(tick_time); + } if ((units_changed & MINUTE_UNIT) == MINUTE_UNIT) { display_time(tick_time); } -#if VIBE_ON_HOUR - if ((units_changed & HOUR_UNIT) == HOUR_UNIT) { + if (settings.vibe_on_hour && (units_changed & HOUR_UNIT) == HOUR_UNIT) { vibes_double_pulse(); } -#endif if ((units_changed & DAY_UNIT) == DAY_UNIT) { display_day(tick_time); display_date(tick_time); } + + if (settings.display_year && (units_changed & YEAR_UNIT) == YEAR_UNIT) { + display_seconds_years(tick_time); + } } void deinit() { + // Settings + persist_write_data(0, &settings, sizeof(Settings)); + // Time for (int i = 0; i < NUMBER_OF_TIME_SLOTS; i++) { unload_digit_image_from_slot(&time_slots[i].slot); @@ -576,8 +637,7 @@ void deinit() { } layer_destroy(seconds_layer); - layer_destroy(footer_layer); window_destroy(window); -} \ No newline at end of file +} diff --git a/src/js/pebble-js-app.js b/src/js/pebble-js-app.js new file mode 100644 index 0000000..8129596 --- /dev/null +++ b/src/js/pebble-js-app.js @@ -0,0 +1,16 @@ +// Open app configuration for PebbleRevolution. +Pebble.addEventListener("showConfiguration", + function(e) { + Pebble.openURL("http://evilrobot69.github.io/PebbleRevolution"); + } +); + +// Store app configuration. +Pebble.addEventListener("webviewclosed", + function(e) { + if (e.response != "") { + var configuration = JSON.parse(decodeURIComponent(e.response)); + Pebble.sendAppMessage(configuration, null, null); + } + } + );