From 01a412444d1f92565f50067fd6643d685d7087ec Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Wed, 30 Dec 2015 18:01:00 +0000 Subject: [PATCH 01/13] Updated build process from SDK 2 to SDK 3 --- appinfo.json | 73 ++++++++++--------- src/js/src/keen.js | 2 +- src/js/src/main.js | 4 +- wscript | 170 ++++++++++++++++++++++++++------------------- 4 files changed, 143 insertions(+), 106 deletions(-) diff --git a/appinfo.json b/appinfo.json index 9e0d25b..b777ecb 100644 --- a/appinfo.json +++ b/appinfo.json @@ -1,32 +1,43 @@ { - "uuid": "f50e354a-e8d9-46be-be74-0c5f488b3a4d", - "shortName": "Readebble", - "longName": "Readebble", - "companyName": "Neal", - "versionCode": 1, - "versionLabel": "2.2", - "capabilities": [ "configurable" ], - "watchapp": { - "watchface": false - }, - "appKeys": { - "type": 0, - "method": 1, - "index": 2, - "title": 3 - }, - "config": { - "keen": { "projectId": "54532b53383144606491d740", "writeKey": "3d2051dfda71165e1f4693d7ad0787911713fcc4156da4556fb3211c4aee9efa6b7a76b5078e785565a4554b18186ed83dd8bcb59eeaf7931f53a576b2fc2b69cb9c936fb97ef1c83d79239165e0b1682ad56887ad3031ca476b9ed536a9d1edfb129ff85dd3193cc43e2b0308024b97" } - }, - "debug": true, - "resources": { - "media": [ - { - "menuIcon": true, - "type": "png", - "name": "IMAGE_MENU_ICON", - "file": "icon.png" - } - ] - } -} + "uuid": "f50e354a-e8d9-46be-be74-0c5f488b3a4d", + "shortName": "Readebble", + "longName": "Readebble", + "companyName": "Neal", + "versionCode": 1, + "versionLabel": "2.2", + "capabilities": [ + "configurable" + ], + "watchapp": { + "watchface": false + }, + "appKeys": { + "type": 0, + "method": 1, + "index": 2, + "title": 3 + }, + "config": { + "keen": { + "projectId": "54532b53383144606491d740", + "writeKey": "3d2051dfda71165e1f4693d7ad0787911713fcc4156da4556fb3211c4aee9efa6b7a76b5078e785565a4554b18186ed83dd8bcb59eeaf7931f53a576b2fc2b69cb9c936fb97ef1c83d79239165e0b1682ad56887ad3031ca476b9ed536a9d1edfb129ff85dd3193cc43e2b0308024b97" + } + }, + "debug": true, + "resources": { + "media": [ + { + "menuIcon": true, + "type": "png", + "name": "IMAGE_MENU_ICON", + "file": "icon.png" + } + ] + }, + "targetPlatforms": [ + "aplite", + "basalt", + "chalk" + ], + "sdkVersion": "3" +} \ No newline at end of file diff --git a/src/js/src/keen.js b/src/js/src/keen.js index 0e22908..f13b8d1 100644 --- a/src/js/src/keen.js +++ b/src/js/src/keen.js @@ -1,6 +1,6 @@ var Keen = { addEvent: function(name, data) { - if (!data || !data instanceof Object) data = {}; + if ((!data) || !(data instanceof Object)) data = {}; data.app = { name: AppInfo.shortName, version: AppInfo.versionLabel, uuid: AppInfo.uuid }; data.user = { accountToken: Pebble.getAccountToken() }; if (AppInfo.debug) { diff --git a/src/js/src/main.js b/src/js/src/main.js index 2fcfb17..8f5806b 100644 --- a/src/js/src/main.js +++ b/src/js/src/main.js @@ -10,8 +10,8 @@ Readebble.bufferSize = 440; Readebble.init = function() { Readebble.subscriptions = JSON.parse(localStorage.getItem('subscriptions')) || []; Readebble.pocket = JSON.parse(localStorage.getItem('pocket')) || {}; - if (!Readebble.subscriptions instanceof Array) Readebble.subscriptions = []; - if (!Readebble.pocket instanceof Object) Readebble.pocket = {}; + if (!(Readebble.subscriptions instanceof Array)) Readebble.subscriptions = []; + if (!(Readebble.pocket instanceof Object)) Readebble.pocket = {}; Readebble.sendSubscriptions(); setTimeout(function() { Keen.addEvent('init', { subscriptions: { count: Readebble.subscriptions.length }, hasPocketToken: (Readebble.pocket.access_token !== 'undefined') }); }, 100); }; diff --git a/wscript b/wscript index 257dc6a..f258540 100644 --- a/wscript +++ b/wscript @@ -1,4 +1,4 @@ -import os +import os.path import json import shutil from sh import uglifyjs @@ -8,100 +8,126 @@ top = '.' out = 'build' def options(ctx): - ctx.load('pebble_sdk') + ctx.load('pebble_sdk') def configure(ctx): - ctx.load('pebble_sdk') + ctx.load('pebble_sdk') def distclean(ctx): - ctx.load('pebble_sdk') - for p in ['build', 'src/generated', 'src/js/src/generated', 'src/js/pebble-js-app.js']: - try: - if os.path.isfile(p): os.remove(p) - elif os.path.isdir(p): shutil.rmtree(p) - except OSError as e: - pass + ctx.load('pebble_sdk') + for p in ['build', 'src/generated', 'src/js/src/generated', 'src/js/pebble-js-app.js']: + try: + if os.path.isfile(p): os.remove(p) + elif os.path.isdir(p): shutil.rmtree(p) + except OSError as e: + pass def build(ctx): - ctx.load('pebble_sdk') + # Create a group to ensure the generated files are created first + ctx.add_group('pregenerate') - # Run jshint on appinfo.json - ctx(rule=js_jshint, source='appinfo.json') + ctx.load('pebble_sdk') - # Run jshint on all the JavaScript files - ctx(rule=js_jshint, source=ctx.path.ant_glob('src/js/src/**/*.js')) + build_worker = os.path.exists('worker_src') + binaries = [] - # Generate appinfo.h - ctx(rule=generate_appinfo_h, source='appinfo.json', target='../src/generated/appinfo.h') + # The following must be generated first + ctx.set_group('pregenerate') - # Generate keys.h - ctx(rule=generate_keys_h, source='src/keys.json', target='../src/generated/keys.h') + # Run jshint on appinfo.json + ctx(rule=js_jshint, source='appinfo.json') - # Generate appinfo.js - ctx(rule=generate_appinfo_js, source='appinfo.json', target='../src/js/src/generated/appinfo.js') + # Run jshint on all the JavaScript files + ctx(rule=js_jshint, source=ctx.path.ant_glob('src/js/src/**/*.js')) - # Generate keys.js - ctx(rule=generate_keys_js, source='src/keys.json', target='../src/js/src/generated/keys.js') + # Generate appinfo.h + ctx(rule=generate_appinfo_h, source='appinfo.json', target='../src/generated/appinfo.h') - # Combine the source JS files into a single JS file. - ctx(rule=concatenate_js, source=ctx.path.ant_glob('src/js/src/**/*.js'), target='../src/js/pebble-js-app.js') + # Generate keys.h + ctx(rule=generate_keys_h, source='src/keys.json', target='../src/generated/keys.h') - # Build and bundle the Pebble app. - ctx.pbl_program(source=ctx.path.ant_glob('src/**/*.c'), target='pebble-app.elf') - ctx.pbl_bundle(elf='pebble-app.elf', js='../src/js/pebble-js-app.js') + # Generate appinfo.js + ctx(rule=generate_appinfo_js, source='appinfo.json', target='../src/js/src/generated/appinfo.js') + + # Generate keys.js + ctx(rule=generate_keys_js, source='src/keys.json', target='../src/js/src/generated/keys.js') + + # Combine the source JS files into a single JS file. + ctx(rule=concatenate_js, source=ctx.path.ant_glob('src/js/src/**/*.js'), target='../src/js/pebble-js-app.js') + + # Now the main build process can happen, building multiple platforms + for p in ctx.env.TARGET_PLATFORMS: + ctx.set_env(ctx.all_envs[p]) + ctx.set_group(ctx.env.PLATFORM_NAME) + app_elf='{}/pebble-app.elf'.format(ctx.env.BUILD_DIR) + ctx.pbl_program(source=ctx.path.ant_glob('src/**/*.c'), + target=app_elf) + + if build_worker: + worker_elf='{}/pebble-worker.elf'.format(ctx.env.BUILD_DIR) + binaries.append({'platform': p, 'app_elf': app_elf, 'worker_elf': worker_elf}) + ctx.pbl_worker(source=ctx.path.ant_glob('worker_src/**/*.c'), + target=worker_elf) + else: + binaries.append({'platform': p, 'app_elf': app_elf}) + + # Bundle everything needed into the pbw file + ctx.set_group('bundle') + ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob('src/js/**/*.js')) def generate_appinfo_h(task): - src = task.inputs[0].abspath() - target = task.outputs[0].abspath() - appinfo = json.load(open(src)) - f = open(target, 'w') - f.write('#pragma once\n\n') - f.write('#define DEBUG {0}\n'.format('true' if appinfo['debug'] else 'false')) - f.write('#define VERSION_LABEL "{0}"\n'.format(appinfo['versionLabel'])) - f.write('#define UUID "{0}"\n'.format(appinfo['uuid'])) - for key in appinfo['appKeys']: - f.write('#define APP_KEY_{0} {1}\n'.format(key.upper(), appinfo['appKeys'][key])) - f.close() + src = task.inputs[0].abspath() + target = task.outputs[0].abspath() + appinfo = json.load(open(src)) + f = open(target, 'w') + f.write('#pragma once\n\n') + f.write('#define DEBUG {0}\n'.format('true' if appinfo['debug'] else 'false')) + f.write('#define VERSION_LABEL "{0}"\n'.format(appinfo['versionLabel'])) + f.write('#define UUID "{0}"\n'.format(appinfo['uuid'])) + for key in appinfo['appKeys']: + f.write('#define APP_KEY_{0} {1}\n'.format(key.upper(), appinfo['appKeys'][key])) + f.close() def generate_keys_h(task): - src = task.inputs[0].abspath() - target = task.outputs[0].abspath() - keys = json.load(open(src)) - f = open(target, 'w') - f.write('#pragma once\n\n') - for key in keys: - f.write('enum {\n') - for key2 in keys[key]: - f.write('\tKEY_{0}_{1},\n'.format(key, key2)) - f.write('};\n') - f.close() + src = task.inputs[0].abspath() + target = task.outputs[0].abspath() + keys = json.load(open(src)) + f = open(target, 'w') + f.write('#pragma once\n\n') + for key in keys: + f.write('enum {\n') + for key2 in keys[key]: + f.write('\tKEY_{0}_{1},\n'.format(key, key2)) + f.write('};\n') + f.close() def generate_appinfo_js(task): - src = task.inputs[0].abspath() - target = task.outputs[0].abspath() - data = open(src).read().strip() - f = open(target, 'w') - f.write('var AppInfo = ') - f.write(data) - f.write(';') - f.close() + src = task.inputs[0].abspath() + target = task.outputs[0].abspath() + data = open(src).read().strip() + f = open(target, 'w') + f.write('var AppInfo = ') + f.write(data) + f.write(';') + f.close() def generate_keys_js(task): - src = task.inputs[0].abspath() - target = task.outputs[0].abspath() - keys = json.load(open(src)) - f = open(target, 'w') - for key in keys: - f.write('var {0} = {{\n'.format(key)) - for i, key2 in enumerate(keys[key]): - f.write('\t{0}: {1},\n'.format(key2, i)) - f.write('};\n') - f.close() + src = task.inputs[0].abspath() + target = task.outputs[0].abspath() + keys = json.load(open(src)) + f = open(target, 'w') + for key in keys: + f.write('var {0} = {{\n'.format(key)) + for i, key2 in enumerate(keys[key]): + f.write('\t{0}: {1},\n'.format(key2, i)) + f.write('};\n') + f.close() def concatenate_js(task): - inputs = (input.abspath() for input in task.inputs) - uglifyjs(*inputs, o=task.outputs[0].abspath(), b=True) + inputs = (input.abspath() for input in task.inputs) + uglifyjs(*inputs, o=task.outputs[0].abspath(), b=True) def js_jshint(task): - inputs = (input.abspath() for input in task.inputs) - jshint(*inputs) + inputs = (input.abspath() for input in task.inputs) + jshint(*inputs) + From 413d5f8fe0d5ef345052da5c3a88704d3be5a053 Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Thu, 31 Dec 2015 20:27:00 +0000 Subject: [PATCH 02/13] Settings menu changed to suit round display --- src/js/src/main.js | 2 +- src/windows/win-settings.c | 148 ++++++++++++++++++-------------- src/windows/win-subscriptions.c | 81 +++++++++++++---- 3 files changed, 148 insertions(+), 83 deletions(-) diff --git a/src/js/src/main.js b/src/js/src/main.js index 8f5806b..9895026 100644 --- a/src/js/src/main.js +++ b/src/js/src/main.js @@ -23,7 +23,7 @@ Readebble.sendError = function(type, err) { Readebble.sendSubscriptions = function() { if (!this.subscriptions.length) { - return Readebble.sendError(TYPE.SUBSCRIPTION, 'No subscriptions found. Use the app settings in the Pebble mobile app to add subscriptions.'); + return Readebble.sendError(TYPE.SUBSCRIPTION, 'No feeds configured'); } appMessageQueue.send({type:TYPE.SUBSCRIPTION, method:METHOD.SIZE, index:Readebble.subscriptions.length}); for (var i = 0; i < Readebble.subscriptions.length; i++) { diff --git a/src/windows/win-settings.c b/src/windows/win-settings.c index b019fa0..ed1007e 100644 --- a/src/windows/win-settings.c +++ b/src/windows/win-settings.c @@ -3,16 +3,17 @@ #include "libs/pebble-assist.h" #include "settings.h" -#define MENU_NUM_SECTIONS 2 -#define MENU_SECTION_HEADLINES 0 -#define MENU_SECTION_SUMMARY 1 - -#define MENU_SECTION_ROWS_HEADLINES 1 -#define MENU_SECTION_ROWS_SUMMARY 2 - -#define MENU_ROW_HEADLINES_SIZE 0 -#define MENU_ROW_SUMMARY_SIZE 0 -#define MENU_ROW_SUMMARY_COLOR 1 +#define MENU_NUM_SECTIONS 1 + +enum { + MENU_ROW_INVALID = -1, + + MENU_ROW_HEADLINES_SIZE, + MENU_ROW_SUMMARY_SIZE, + MENU_ROW_SUMMARY_COLOR, + + MENU_ROW_NUM +} MENU_ROW; static uint16_t menu_get_num_sections_callback(struct MenuLayer *menu_layer, void *callback_context); static uint16_t menu_get_num_rows_callback(struct MenuLayer *menu_layer, uint16_t section_index, void *callback_context); @@ -26,6 +27,16 @@ static void window_unload(Window *window); static Window *window = NULL; static MenuLayer *menu_layer = NULL; +#ifdef PBL_SDK_3 +static StatusBarLayer *s_status_bar; +static TextLayer *s_lower_bar; +#endif + +static char *settings_labels[MENU_ROW_NUM] = { + "Headline font size", + "Story font fize", + "Story text color" +}; void win_settings_init(void) { window = window_create(); @@ -50,89 +61,71 @@ static uint16_t menu_get_num_sections_callback(struct MenuLayer *menu_layer, voi } static uint16_t menu_get_num_rows_callback(struct MenuLayer *menu_layer, uint16_t section_index, void *callback_context) { - switch (section_index) { - case MENU_SECTION_HEADLINES: - return MENU_SECTION_ROWS_HEADLINES; - case MENU_SECTION_SUMMARY: - return MENU_SECTION_ROWS_SUMMARY; - default: - return 0; - } + return MENU_ROW_NUM; } static int16_t menu_get_header_height_callback(struct MenuLayer *menu_layer, uint16_t section_index, void *callback_context) { - return MENU_CELL_BASIC_HEADER_HEIGHT; + return 0; } static int16_t menu_get_cell_height_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context) { +#ifdef PBL_RECT return 38; +#else + if (menu_layer_is_index_selected(menu_layer, cell_index)) { + return MENU_CELL_ROUND_FOCUSED_SHORT_CELL_HEIGHT; + } + else { + return MENU_CELL_ROUND_UNFOCUSED_TALL_CELL_HEIGHT; + } +#endif } static void menu_draw_header_callback(GContext *ctx, const Layer *cell_layer, uint16_t section_index, void *callback_context) { - switch (section_index) { - case MENU_SECTION_HEADLINES: - menu_cell_basic_header_draw(ctx, cell_layer, "Headlines"); - break; - case MENU_SECTION_SUMMARY: - menu_cell_basic_header_draw(ctx, cell_layer, "Story"); - break; - } + // Do nothing } static void menu_draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *callback_context) { - char label[12] = ""; char value[6] = ""; - switch (cell_index->section) { - case MENU_SECTION_HEADLINES: - switch (cell_index->row) { - case MENU_ROW_HEADLINES_SIZE: - strcpy(label, "Font Size"); - strcpy(value, settings()->headlines_font_size ? "Large": "Small"); - break; - } + switch (cell_index->row) { + case MENU_ROW_HEADLINES_SIZE: + strncpy(value, settings()->headlines_font_size ? "Large": "Small", sizeof(value)); + break; + case MENU_ROW_SUMMARY_SIZE: + strncpy(value, settings()->story_font_size ? "Large": "Small", sizeof(value)); break; - case MENU_SECTION_SUMMARY: - switch (cell_index->row) { - case MENU_ROW_SUMMARY_SIZE: - strcpy(label, "Font Size"); - strcpy(value, settings()->story_font_size ? "Large": "Small"); - break; - case MENU_ROW_SUMMARY_COLOR: - strcpy(label, "Font Color"); - strcpy(value, settings()->story_font_color ? "White": "Black"); - break; - } + case MENU_ROW_SUMMARY_COLOR: + strncpy(value, settings()->story_font_color ? "White": "Black", sizeof(value)); break; } +#ifdef PBL_RECT graphics_context_set_text_color(ctx, GColorBlack); - graphics_draw_text(ctx, label, fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(4, 2, 136, 28), GTextOverflowModeTrailingEllipsis, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, settings_labels[cell_index->row], fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(4, 2, 136, 28), GTextOverflowModeTrailingEllipsis, GTextAlignmentLeft, NULL); graphics_draw_text(ctx, value, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), GRect(4, 7, 134, 24), GTextOverflowModeTrailingEllipsis, GTextAlignmentRight, NULL); +#else + menu_cell_basic_draw(ctx, cell_layer, settings_labels[cell_index->row], value, NULL); +#endif } static void menu_select_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context) { - switch (cell_index->section) { - case MENU_SECTION_HEADLINES: - switch (cell_index->row) { - case MENU_ROW_HEADLINES_SIZE: - settings()->headlines_font_size = !settings()->headlines_font_size; - break; - } + switch (cell_index->row) { + case MENU_ROW_HEADLINES_SIZE: + settings()->headlines_font_size = !settings()->headlines_font_size; break; - case MENU_SECTION_SUMMARY: - switch (cell_index->row) { - case MENU_ROW_SUMMARY_SIZE: - settings()->story_font_size = !settings()->story_font_size; - break; - case MENU_ROW_SUMMARY_COLOR: - settings()->story_font_color = !settings()->story_font_color; - break; - } + case MENU_ROW_SUMMARY_SIZE: + settings()->story_font_size = !settings()->story_font_size; + break; + case MENU_ROW_SUMMARY_COLOR: + settings()->story_font_color = !settings()->story_font_color; break; } menu_layer_reload_data(menu_layer); } static void window_load(Window *window) { + Layer *window_layer = window_get_root_layer(window); + GRect bounds = layer_get_bounds(window_layer); + menu_layer = menu_layer_create_fullscreen(window); menu_layer_set_callbacks(menu_layer, NULL, (MenuLayerCallbacks) { .get_num_sections = menu_get_num_sections_callback, @@ -145,8 +138,35 @@ static void window_load(Window *window) { }); menu_layer_set_click_config_onto_window(menu_layer, window); menu_layer_add_to_window(menu_layer, window); + +#ifdef PBL_SDK_3 + // Set up the status bar if it's needed + s_status_bar = status_bar_layer_create(); + layer_add_child(window_layer, status_bar_layer_get_layer(s_status_bar)); + status_bar_layer_set_colors(s_status_bar, GColorWhite, GColorBlack); + + // Set up the lower message bar + const GEdgeInsets message_insets = {.top = bounds.size.h - STATUS_BAR_LAYER_HEIGHT}; + s_lower_bar = text_layer_create(grect_inset(bounds, message_insets)); + text_layer_set_text_alignment(s_lower_bar, GTextAlignmentCenter); + text_layer_set_colors(s_lower_bar, GColorBlack, GColorWhite); + text_layer_set_text(s_lower_bar, ""); + layer_add_child(window_layer, text_layer_get_layer(s_lower_bar)); +#endif + +#ifdef PBL_COLOR + menu_layer_set_normal_colors(menu_layer, GColorWhite, GColorBlack); + menu_layer_set_highlight_colors(menu_layer, GColorOrange, GColorWhite); +#endif } static void window_unload(Window *window) { menu_layer_destroy_safe(menu_layer); + +#ifdef PBL_SDK_3 + // Destroy the status bar if there is one + status_bar_layer_destroy(s_status_bar); + text_layer_destroy(s_lower_bar); +#endif } + diff --git a/src/windows/win-subscriptions.c b/src/windows/win-subscriptions.c index 61e9f02..a44a303 100644 --- a/src/windows/win-subscriptions.c +++ b/src/windows/win-subscriptions.c @@ -6,6 +6,11 @@ #include "win-headlines.h" #include "win-settings.h" +#define MENU_NUM_SECTIONS (1) +#define TEXT_BORDER_INSET (16) + +#define GRECT_EDGE_TRIM(RECT, AMOUNT) RECT.origin.x += AMOUNT; RECT.size.w -= (AMOUNT * 2); + static uint16_t menu_get_num_sections_callback(struct MenuLayer *menu_layer, void *callback_context); static uint16_t menu_get_num_rows_callback(struct MenuLayer *menu_layer, uint16_t section_index, void *callback_context); static int16_t menu_get_header_height_callback(struct MenuLayer *menu_layer, uint16_t section_index, void *callback_context); @@ -16,9 +21,32 @@ static void menu_select_callback(struct MenuLayer *menu_layer, MenuIndex *cell_i static void menu_select_long_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context); static void window_load(Window *window); static void window_unload(Window *window); +int menu_item_count(); +int menu_item_settings_pos(); static Window *window = NULL; static MenuLayer *menu_layer = NULL; +#ifdef PBL_SDK_3 +static StatusBarLayer *s_status_bar; +#endif + +int menu_item_count() { + int items; + items = subscriptions_count() + 1; + if (items < 2) { + items = 2; + } + return items; +} + +int menu_item_settings_pos() { + int position; + position = subscriptions_count(); + if (position < 1) { + position = 1; + } + return position; +} void win_subscriptions_init(void) { window = window_create(); @@ -41,50 +69,46 @@ void win_subscriptions_reload_data_and_mark_dirty(void) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // static uint16_t menu_get_num_sections_callback(struct MenuLayer *menu_layer, void *callback_context) { - return 2; + return MENU_NUM_SECTIONS; } static uint16_t menu_get_num_rows_callback(struct MenuLayer *menu_layer, uint16_t section_index, void *callback_context) { - if (section_index == 1) return 1; - return subscriptions_count() ? subscriptions_count() : 1; + return menu_item_count(); } static int16_t menu_get_header_height_callback(struct MenuLayer *menu_layer, uint16_t section_index, void *callback_context) { - return MENU_CELL_BASIC_HEADER_HEIGHT; + return 0; } static int16_t menu_get_cell_height_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context) { - if (cell_index->section == 1) return MENU_CELL_BASIC_CELL_HEIGHT; + if (cell_index->row == menu_item_settings_pos()) return MENU_CELL_BASIC_CELL_HEIGHT; if (subscriptions_get_error()) { - return graphics_text_layout_get_content_size(subscriptions_get_error(), fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), GRect(4, 2, 136, 128), GTextOverflowModeFill, GTextAlignmentLeft).h + 12; + GRect bounds = layer_get_bounds(menu_layer_get_layer(menu_layer)); + GRECT_EDGE_TRIM (bounds, TEXT_BORDER_INSET) + return graphics_text_layout_get_content_size(subscriptions_get_error(), fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), bounds, GTextOverflowModeFill, GTextAlignmentLeft).h + 12; } return MENU_CELL_BASIC_CELL_HEIGHT; } static void menu_draw_header_callback(GContext *ctx, const Layer *cell_layer, uint16_t section_index, void *callback_context) { - switch (section_index) { - case 0: - menu_cell_basic_header_draw(ctx, cell_layer, "Readebble"); - break; - case 1: - menu_cell_basic_header_draw(ctx, cell_layer, "Other"); - break; - } + // Do nothing } static void menu_draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *callback_context) { - if (cell_index->section == 1) { + if (cell_index->row == menu_item_settings_pos()) { menu_cell_basic_draw(ctx, cell_layer, "Settings", NULL, NULL); } else if (subscriptions_get_error()) { - graphics_context_set_text_color(ctx, GColorBlack); - graphics_draw_text(ctx, subscriptions_get_error(), fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), GRect(4, 2, 136, 128), GTextOverflowModeFill, GTextAlignmentLeft, NULL); + //graphics_context_set_text_color(ctx, GColorBlack); + GRect bounds = layer_get_bounds(cell_layer); + GRECT_EDGE_TRIM (bounds, TEXT_BORDER_INSET) + graphics_draw_text(ctx, subscriptions_get_error(), fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), bounds, GTextOverflowModeFill, PBL_IF_ROUND_ELSE (GTextAlignmentCenter, GTextAlignmentLeft), NULL); } else { menu_cell_basic_draw(ctx, cell_layer, subscriptions_get(cell_index->row)->title, NULL, NULL); } } static void menu_select_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context) { - if (cell_index->section == 1) { + if (cell_index->row == menu_item_settings_pos()) { return win_settings_push(); } if (!subscriptions_count()) return; @@ -97,6 +121,8 @@ static void menu_select_long_callback(struct MenuLayer *menu_layer, MenuIndex *c } static void window_load(Window *window) { + Layer *window_layer = window_get_root_layer(window); + menu_layer = menu_layer_create_fullscreen(window); menu_layer_set_callbacks(menu_layer, NULL, (MenuLayerCallbacks) { .get_num_sections = menu_get_num_sections_callback, @@ -110,8 +136,27 @@ static void window_load(Window *window) { }); menu_layer_set_click_config_onto_window(menu_layer, window); menu_layer_add_to_window(menu_layer, window); + +#ifdef PBL_SDK_3 + // Set up the status bar if it's needed + s_status_bar = status_bar_layer_create(); + layer_add_child(window_layer, status_bar_layer_get_layer(s_status_bar)); + status_bar_layer_set_colors(s_status_bar, GColorWhite, GColorBlack); +#endif + +#ifdef PBL_COLOR + menu_layer_set_normal_colors(menu_layer, GColorWhite, GColorBlack); + menu_layer_set_highlight_colors(menu_layer, GColorOrange, GColorWhite); +#endif } static void window_unload(Window *window) { menu_layer_destroy_safe(menu_layer); + +#ifdef PBL_SDK_3 + // Destroy the status bar if there is one + status_bar_layer_destroy(s_status_bar); +#endif } + + From bc12dc74d161a29d141d9cbbe0f16bda54aa3241 Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Sat, 2 Jan 2016 01:21:23 +0000 Subject: [PATCH 03/13] Initial changes to headline display to suit round faces --- src/windows/win-headlines.c | 48 ++++++++++++++++++++++++++++----- src/windows/win-subscriptions.c | 12 +++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/windows/win-headlines.c b/src/windows/win-headlines.c index 32769fe..09efb12 100644 --- a/src/windows/win-headlines.c +++ b/src/windows/win-headlines.c @@ -7,6 +7,10 @@ #include "rss.h" #include "win-story.h" +#define TEXT_BORDER_INSET (16) + +#define GRECT_EDGE_TRIM(RECT, AMOUNT) RECT.origin.x += AMOUNT; RECT.size.w -= (AMOUNT * 2); + static uint16_t menu_get_num_rows_callback(struct MenuLayer *menu_layer, uint16_t section_index, void *callback_context); static int16_t menu_get_header_height_callback(struct MenuLayer *menu_layer, uint16_t section_index, void *callback_context); static int16_t menu_get_cell_height_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context); @@ -19,6 +23,9 @@ static void window_unload(Window *window); static Window *window = NULL; static MenuLayer *menu_layer = NULL; +#ifdef PBL_SDK_3 +static TextLayer *s_status_bar; +#endif void win_headlines_init(void) { window = window_create(); @@ -49,26 +56,30 @@ static uint16_t menu_get_num_rows_callback(struct MenuLayer *menu_layer, uint16_ } static int16_t menu_get_header_height_callback(struct MenuLayer *menu_layer, uint16_t section_index, void *callback_context) { - return MENU_CELL_BASIC_HEADER_HEIGHT; + return 0;//MENU_CELL_BASIC_HEADER_HEIGHT; } static int16_t menu_get_cell_height_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context) { + GRect bounds = layer_get_bounds(menu_layer_get_layer(menu_layer)); + GRECT_EDGE_TRIM (bounds, TEXT_BORDER_INSET) if (headlines_get_error()) { - return graphics_text_layout_get_content_size(headlines_get_error(), fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), GRect(4, 2, 136, 128), GTextOverflowModeFill, GTextAlignmentLeft).h + 12; + return graphics_text_layout_get_content_size(headlines_get_error(), fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), bounds, GTextOverflowModeFill, GTextAlignmentLeft).h + 12; } - return graphics_text_layout_get_content_size(headlines_get(cell_index->row)->title, fonts_get_system_font(settings()->headlines_font_size ? FONT_KEY_GOTHIC_24 : FONT_KEY_GOTHIC_18), GRect(2, 0, 140, 128), GTextOverflowModeFill, GTextAlignmentLeft).h + (settings()->headlines_font_size ? 10 : 8); + return graphics_text_layout_get_content_size(headlines_get(cell_index->row)->title, fonts_get_system_font(settings()->headlines_font_size ? FONT_KEY_GOTHIC_24 : FONT_KEY_GOTHIC_18), bounds, GTextOverflowModeFill, GTextAlignmentLeft).h + (settings()->headlines_font_size ? 10 : 8); } static void menu_draw_header_callback(GContext *ctx, const Layer *cell_layer, uint16_t section_index, void *callback_context) { - menu_cell_basic_header_draw(ctx, cell_layer, subscriptions_get_current()->title); + //menu_cell_basic_header_draw(ctx, cell_layer, subscriptions_get_current()->title); } static void menu_draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *callback_context) { + GRect bounds = layer_get_bounds(menu_layer_get_layer(menu_layer)); + GRECT_EDGE_TRIM (bounds, TEXT_BORDER_INSET) graphics_context_set_text_color(ctx, GColorBlack); if (headlines_get_error()) { - graphics_draw_text(ctx, headlines_get_error(), fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), GRect(4, 2, 136, 128), GTextOverflowModeFill, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, headlines_get_error(), fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), bounds, GTextOverflowModeFill, PBL_IF_ROUND_ELSE(GTextAlignmentCenter, GTextAlignmentLeft), NULL); } else { - graphics_draw_text(ctx, headlines_get(cell_index->row)->title, fonts_get_system_font(settings()->headlines_font_size ? FONT_KEY_GOTHIC_24 : FONT_KEY_GOTHIC_18), GRect(2, 0, 140, 128), GTextOverflowModeFill, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, headlines_get(cell_index->row)->title, fonts_get_system_font(settings()->headlines_font_size ? FONT_KEY_GOTHIC_24 : FONT_KEY_GOTHIC_18), bounds, GTextOverflowModeFill, PBL_IF_ROUND_ELSE(GTextAlignmentCenter, GTextAlignmentLeft), NULL); } } @@ -85,6 +96,9 @@ static void menu_select_long_callback(struct MenuLayer *menu_layer, MenuIndex *c } static void window_load(Window *window) { + Layer *window_layer = window_get_root_layer(window); + GRect bounds = layer_get_bounds(window_layer); + menu_layer = menu_layer_create_fullscreen(window); menu_layer_set_callbacks(menu_layer, NULL, (MenuLayerCallbacks) { .get_num_rows = menu_get_num_rows_callback, @@ -97,8 +111,30 @@ static void window_load(Window *window) { }); menu_layer_set_click_config_onto_window(menu_layer, window); menu_layer_add_to_window(menu_layer, window); + +#ifdef PBL_SDK_3 + // Set up the status bar if it's needed + GRect bar_bounds = bounds; + bar_bounds.size.h = STATUS_BAR_LAYER_HEIGHT; + s_status_bar = text_layer_create(bar_bounds); + text_layer_set_text_alignment(s_status_bar, GTextAlignmentCenter); + text_layer_set_colors(s_status_bar, GColorBlack, GColorWhite); + text_layer_set_text(s_status_bar, subscriptions_get_current()->title); + layer_add_child(window_layer, text_layer_get_layer(s_status_bar)); +#endif + +#ifdef PBL_COLOR + menu_layer_set_normal_colors(menu_layer, GColorWhite, GColorBlack); + menu_layer_set_highlight_colors(menu_layer, GColorOrange, GColorWhite); +#endif } static void window_unload(Window *window) { menu_layer_destroy_safe(menu_layer); + +#ifdef PBL_SDK_3 + // Destroy the status bar if there is one + text_layer_destroy(s_status_bar); +#endif } + diff --git a/src/windows/win-subscriptions.c b/src/windows/win-subscriptions.c index a44a303..e193182 100644 --- a/src/windows/win-subscriptions.c +++ b/src/windows/win-subscriptions.c @@ -28,6 +28,7 @@ static Window *window = NULL; static MenuLayer *menu_layer = NULL; #ifdef PBL_SDK_3 static StatusBarLayer *s_status_bar; +static TextLayer *s_lower_bar; #endif int menu_item_count() { @@ -96,6 +97,7 @@ static void menu_draw_header_callback(GContext *ctx, const Layer *cell_layer, ui static void menu_draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *callback_context) { if (cell_index->row == menu_item_settings_pos()) { + graphics_context_set_text_color(ctx, GColorBlue); menu_cell_basic_draw(ctx, cell_layer, "Settings", NULL, NULL); } else if (subscriptions_get_error()) { //graphics_context_set_text_color(ctx, GColorBlack); @@ -122,6 +124,7 @@ static void menu_select_long_callback(struct MenuLayer *menu_layer, MenuIndex *c static void window_load(Window *window) { Layer *window_layer = window_get_root_layer(window); + GRect bounds = layer_get_bounds(window_layer); menu_layer = menu_layer_create_fullscreen(window); menu_layer_set_callbacks(menu_layer, NULL, (MenuLayerCallbacks) { @@ -142,6 +145,14 @@ static void window_load(Window *window) { s_status_bar = status_bar_layer_create(); layer_add_child(window_layer, status_bar_layer_get_layer(s_status_bar)); status_bar_layer_set_colors(s_status_bar, GColorWhite, GColorBlack); + + // Set up the lower message bar + const GEdgeInsets message_insets = {.top = bounds.size.h - STATUS_BAR_LAYER_HEIGHT}; + s_lower_bar = text_layer_create(grect_inset(bounds, message_insets)); + text_layer_set_text_alignment(s_lower_bar, GTextAlignmentCenter); + text_layer_set_colors(s_lower_bar, GColorBlack, GColorWhite); + text_layer_set_text(s_lower_bar, ""); + layer_add_child(window_layer, text_layer_get_layer(s_lower_bar)); #endif #ifdef PBL_COLOR @@ -156,6 +167,7 @@ static void window_unload(Window *window) { #ifdef PBL_SDK_3 // Destroy the status bar if there is one status_bar_layer_destroy(s_status_bar); + text_layer_destroy(s_lower_bar); #endif } From 4baf9b648e45a4c3e6e3e0380e0da684a70259aa Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Mon, 4 Jan 2016 00:52:06 +0000 Subject: [PATCH 04/13] Added progress bar to headline list --- src/headlines.c | 10 +++ src/headlines.h | 1 + src/layers/progress_bar.c | 154 ++++++++++++++++++++++++++++++++++++ src/layers/progress_bar.h | 24 ++++++ src/windows/win-headlines.c | 25 +++++- 5 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 src/layers/progress_bar.c create mode 100644 src/layers/progress_bar.h diff --git a/src/headlines.c b/src/headlines.c index cda95d6..7e51d47 100644 --- a/src/headlines.c +++ b/src/headlines.c @@ -10,10 +10,12 @@ static Headline *headlines = NULL; static uint8_t num_headlines = 0; static uint8_t current_headline = 0; +static uint8_t progress = 0; static char *error = NULL; void headlines_init(void) { + progress = 0; win_headlines_init(); } @@ -33,6 +35,7 @@ void headlines_in_received_handler(DictionaryIterator *iter) { if (!tuple) break; error = malloc(tuple->length); strncpy(error, tuple->value->cstring, tuple->length); + progress = 100; headlines_reload_data_and_mark_dirty(); break; } @@ -41,6 +44,7 @@ void headlines_in_received_handler(DictionaryIterator *iter) { tuple = dict_find(iter, APP_KEY_INDEX); if (!tuple) break; num_headlines = tuple->value->uint8; + progress = (num_headlines == 0 ? 100 : 0); headlines = malloc(sizeof(Headline) * num_headlines); if (headlines == NULL) num_headlines = 0; break; @@ -55,6 +59,7 @@ void headlines_in_received_handler(DictionaryIterator *iter) { if (tuple) { strncpy(headline->title, tuple->value->cstring, sizeof(headline->title) - 1); } + progress = ((int)(index + 1) * 100) / num_headlines; LOG("headline: %d '%s'", headline->index, headline->title); headlines_reload_data_and_mark_dirty(); break; @@ -66,6 +71,10 @@ void headlines_reload_data_and_mark_dirty() { win_headlines_reload_data_and_mark_dirty(); } +uint8_t headlines_progress() { + return progress; +} + uint8_t headlines_count() { return num_headlines; } @@ -105,3 +114,4 @@ void headlines_request() { app_message_outbox_send(); headlines_reload_data_and_mark_dirty(); } + diff --git a/src/headlines.h b/src/headlines.h index 05f5914..12c8652 100644 --- a/src/headlines.h +++ b/src/headlines.h @@ -12,6 +12,7 @@ void headlines_deinit(void); void headlines_in_received_handler(DictionaryIterator *iter); void headlines_reload_data_and_mark_dirty(); uint8_t headlines_count(); +uint8_t headlines_progress(); char* headlines_get_error(); Headline* headlines_get(uint8_t index); Headline* headlines_get_current(); diff --git a/src/layers/progress_bar.c b/src/layers/progress_bar.c new file mode 100644 index 0000000..449bfe3 --- /dev/null +++ b/src/layers/progress_bar.c @@ -0,0 +1,154 @@ +#include +#include "layers/progress_bar.h" + +typedef struct _ProgressBarData { + //Layer *layer; + uint8_t progress; + ProgressBarLayerUpdateProc update_proc; + GColor complete; + GColor remaining; +} ProgressBarData; + +static void progress_bar_layer_update_proc(ProgressBarLayer *progress_bar_layer, GContext *ctx); +float math_sqrt(const float num); + + +ProgressBarLayer * progress_bar_layer_create_fullscreen(Window * window) { + GRect bounds = layer_get_bounds(window_get_root_layer(window)); + GPoint start = GPoint(0, STATUS_BAR_LAYER_HEIGHT - 2); + int16_t width = bounds.size.w; + + ProgressBarLayer *progress_bar_layer = progress_bar_layer_create(start, width); + + Layer *window_layer = window_get_root_layer(window); + layer_add_child(window_layer, progress_bar_layer_get_layer(progress_bar_layer)); + + return progress_bar_layer; +} + +ProgressBarLayer * progress_bar_layer_create(GPoint start, int16_t width) { + // Set up the progress layer + GRect bounds = (GRect){ + .origin = start, + .size = GSize(width, 1) + }; + + ProgressBarLayer *progress_bar_layer = layer_create_with_data(bounds, sizeof(ProgressBarData)); + ProgressBarData *progress_bar_data = (ProgressBarData *)layer_get_data((Layer *)progress_bar_layer); + progress_bar_data->progress = 0; + progress_bar_data->complete = GColorBlack; + progress_bar_data->remaining = GColorWhite; + progress_bar_data->update_proc = NULL; + + layer_set_update_proc(progress_bar_layer, progress_bar_layer_update_proc); + + return progress_bar_layer; +} + +void progress_bar_layer_stretch(ProgressBarLayer * progress_bar_layer) { + GRect window_bounds = layer_get_bounds(window_get_root_layer(layer_get_window((Layer *)progress_bar_layer))); + GRect layer_bounds = layer_get_bounds((Layer *)progress_bar_layer); + + layer_bounds.origin.x = 0; + layer_bounds.size.w = window_bounds.size.w; + layer_set_frame((Layer *)progress_bar_layer, layer_bounds); +} + +void progress_bar_layer_add_to_window(ProgressBarLayer * progress_bar_layer, Window *window) { + layer_add_child(window_get_root_layer(window), (Layer *)progress_bar_layer); +} + +void progress_bar_layer_destroy(ProgressBarLayer * progress_bar_layer) { + // Disconnect from other layers + layer_remove_child_layers((Layer *)progress_bar_layer); + layer_remove_from_parent((Layer *)progress_bar_layer); + + // Free all memory + layer_destroy((Layer *)progress_bar_layer); +} + +void progress_bar_layer_set_pos(ProgressBarLayer * progress_bar_layer, int16_t y) { + GRect window_bounds = layer_get_bounds(window_get_root_layer(layer_get_window((Layer *)progress_bar_layer))); + + float radius = ((float)window_bounds.size.h / 2.0); + float offset = (radius - (float)y); + int16_t width = (int16_t)math_sqrt((radius * radius) - (offset * offset)); + + GRect layer_bounds = (GRect){ + .origin = GPoint((window_bounds.size.w / 2) - width + 4, y), + .size = GSize(width * 2 - 8, 1) + }; + layer_set_frame((Layer *)progress_bar_layer, layer_bounds); +} + +void progress_bar_layer_set_progress(ProgressBarLayer * progress_bar_layer, uint8_t percent) { + ProgressBarData *progress_bar_data = (ProgressBarData *)layer_get_data((Layer *)progress_bar_layer); + + progress_bar_data->progress = percent; + layer_mark_dirty((Layer *)progress_bar_layer); +} + +//Layer * progress_bar_layer_get_layer(ProgressBarLayer * progress_bar_layer) { +// return (Layer *)progress_bar_layer; +//} + +void progress_bar_layer_set_colors(ProgressBarLayer * progress_bar_layer, GColor complete, GColor remaining) { + ProgressBarData *progress_bar_data = (ProgressBarData *)layer_get_data((Layer *)progress_bar_layer); + + progress_bar_data->complete = complete; + progress_bar_data->remaining = remaining; + layer_mark_dirty((Layer *)progress_bar_layer); +} + +GColor progress_bar_layer_get_complete_color(ProgressBarLayer * progress_bar_layer) { + ProgressBarData *progress_bar_data = (ProgressBarData *)layer_get_data((Layer *)progress_bar_layer); + + return progress_bar_data->complete; +} + +GColor progress_bar_layer_get_remaining_color(ProgressBarLayer * progress_bar_layer) { + ProgressBarData *progress_bar_data = (ProgressBarData *)layer_get_data((Layer *)progress_bar_layer); + + return progress_bar_data->remaining; +} + +void progress_bar_layer_set_update_proc(ProgressBarLayer * progress_bar_layer, ProgressBarLayerUpdateProc update_proc) { + ProgressBarData *progress_bar_data = (ProgressBarData *)layer_get_data((Layer *)progress_bar_layer); + + progress_bar_data->update_proc = update_proc; +} + +static void progress_bar_layer_update_proc(Layer *layer, GContext *ctx) { + ProgressBarData *progress_bar_data = (ProgressBarData *)layer_get_data(layer); + + if (progress_bar_data->update_proc != NULL) { + progress_bar_data->update_proc((ProgressBarLayer *)layer, ctx); + } + else { + GRect bounds = layer_get_bounds(layer); + + int width = (int)(float)(((float)progress_bar_data->progress / 100.0f) * bounds.size.w); + // Complete + graphics_context_set_stroke_color(ctx, progress_bar_data->complete); + graphics_draw_line(ctx, GPointZero, GPoint(width, 0)); + // Remaining + graphics_context_set_stroke_color(ctx, progress_bar_data->remaining); + graphics_draw_line(ctx, GPoint(width, 0), GPoint(bounds.size.w, 0)); + } +} + +// See https://forums.getpebble.com/discussion/comment/79122/#Comment_79122 +float math_sqrt(const float num) { + const uint MAX_STEPS = 40; + const float MAX_ERROR = 0.001; + + float answer = num; + float ans_sqr = answer * answer; + uint step = 0; + while((ans_sqr - num > MAX_ERROR) && (step++ < MAX_STEPS)) { + answer = (answer + (num / answer)) / 2; + ans_sqr = answer * answer; + } + return answer; +} + diff --git a/src/layers/progress_bar.h b/src/layers/progress_bar.h new file mode 100644 index 0000000..e167262 --- /dev/null +++ b/src/layers/progress_bar.h @@ -0,0 +1,24 @@ +#pragma once + +#define PROGRESS_BAR_WINDOW_SIZE (GSize(144, 1)) + +typedef Layer ProgressBarLayer; +typedef void(* ProgressBarLayerUpdateProc)(ProgressBarLayer *layer, GContext *ctx); + +#define progress_bar_layer_get_layer(layer) (Layer *)layer +#define progress_bar_layer_destroy_safe(layer) if (layer != NULL) { progress_bar_layer_destroy(layer); layer = NULL; } + +ProgressBarLayer * progress_bar_layer_create(GPoint start, int16_t width); +void progress_bar_layer_destroy(ProgressBarLayer * progress_bar_layer); +void progress_bar_layer_set_pos(ProgressBarLayer * progress_bar_layer, int16_t y); +void progress_bar_layer_set_progress(ProgressBarLayer * progress_bar_layer, uint8_t percent); +//Layer * progress_bar_layer_get_layer(ProgressBarLayer * progress_bar_layer); +void progress_bar_layer_set_colors(ProgressBarLayer * progress_bar_layer, GColor complete, GColor remaining); +GColor progress_bar_layer_get_complete_color(ProgressBarLayer * progress_bar_layer); +GColor progress_bar_layer_get_remaining_color(ProgressBarLayer * progress_bar_layer); +void progress_bar_layer_set_update_proc(ProgressBarLayer * progress_bar_layer, ProgressBarLayerUpdateProc update_proc); + +void progress_bar_layer_stretch(ProgressBarLayer * progress_bar_layer); +ProgressBarLayer * progress_bar_layer_create_fullscreen(Window * window); + + diff --git a/src/windows/win-headlines.c b/src/windows/win-headlines.c index 09efb12..1f19b4e 100644 --- a/src/windows/win-headlines.c +++ b/src/windows/win-headlines.c @@ -6,6 +6,7 @@ #include "subscriptions.h" #include "rss.h" #include "win-story.h" +#include "layers/progress_bar.h" #define TEXT_BORDER_INSET (16) @@ -23,6 +24,7 @@ static void window_unload(Window *window); static Window *window = NULL; static MenuLayer *menu_layer = NULL; +static ProgressBarLayer *s_progress_bar_layer; #ifdef PBL_SDK_3 static TextLayer *s_status_bar; #endif @@ -46,6 +48,7 @@ void win_headlines_deinit(void) { void win_headlines_reload_data_and_mark_dirty(void) { if (!window_is_loaded(window)) return; + progress_bar_layer_set_progress(s_progress_bar_layer, headlines_progress()); menu_layer_reload_data_and_mark_dirty(menu_layer); } @@ -112,21 +115,36 @@ static void window_load(Window *window) { menu_layer_set_click_config_onto_window(menu_layer, window); menu_layer_add_to_window(menu_layer, window); +#define STATUS_BAR_SIZE_MAX (STATUS_BAR_LAYER_HEIGHT + 12) + #ifdef PBL_SDK_3 // Set up the status bar if it's needed GRect bar_bounds = bounds; - bar_bounds.size.h = STATUS_BAR_LAYER_HEIGHT; + bar_bounds.size.h = STATUS_BAR_LAYER_HEIGHT + 12; s_status_bar = text_layer_create(bar_bounds); text_layer_set_text_alignment(s_status_bar, GTextAlignmentCenter); - text_layer_set_colors(s_status_bar, GColorBlack, GColorWhite); + text_layer_set_colors(s_status_bar, GColorBlack, GColorPastelYellow); text_layer_set_text(s_status_bar, subscriptions_get_current()->title); layer_add_child(window_layer, text_layer_get_layer(s_status_bar)); + text_layer_enable_screen_text_flow_and_paging(s_status_bar, 2); + GSize size = text_layer_get_content_size(s_status_bar); + size.h += 4; + size.w = bounds.size.w; + if (size.h > STATUS_BAR_SIZE_MAX) { + size.h = STATUS_BAR_SIZE_MAX; + } + text_layer_set_size(s_status_bar, size); #endif #ifdef PBL_COLOR menu_layer_set_normal_colors(menu_layer, GColorWhite, GColorBlack); menu_layer_set_highlight_colors(menu_layer, GColorOrange, GColorWhite); #endif + + // Set up the progress layer + s_progress_bar_layer = progress_bar_layer_create_fullscreen(window); + + progress_bar_layer_set_pos(s_progress_bar_layer, STATUS_BAR_LAYER_HEIGHT); } static void window_unload(Window *window) { @@ -136,5 +154,8 @@ static void window_unload(Window *window) { // Destroy the status bar if there is one text_layer_destroy(s_status_bar); #endif + + // Destroy the progress bar + progress_bar_layer_destroy(s_progress_bar_layer); } From 1b34b0a7b4505089117ff5b2c1ebe02e8cee94b2 Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Wed, 6 Jan 2016 23:04:33 +0000 Subject: [PATCH 05/13] Add feed title, story scroll and load progress bar Add a title bar layer 'class' used to show the feed on the headline menulist page. Fix the layout of the story page on round watchfaces (may break formatting for rectangular faces). Allow the story to flow and scroll correctly. Provide a progress load bar for transfering the story from phone to watch. To achieve this the buffer size is decreased to 128 bytes, which may need tweaking. --- src/js/src/main.js | 1 + src/layers/progress_bar.c | 14 +--- src/layers/progress_bar.h | 4 - src/layers/title_bar.c | 162 ++++++++++++++++++++++++++++++++++++ src/layers/title_bar.h | 22 +++++ src/rss.c | 8 +- src/story.c | 32 ++++++- src/story.h | 2 + src/windows/win-headlines.c | 31 +++---- src/windows/win-story.c | 126 ++++++++++++++++++++++------ src/windows/win-story.h | 1 + 11 files changed, 342 insertions(+), 61 deletions(-) create mode 100644 src/layers/title_bar.c create mode 100644 src/layers/title_bar.h diff --git a/src/js/src/main.js b/src/js/src/main.js index 9895026..205928e 100644 --- a/src/js/src/main.js +++ b/src/js/src/main.js @@ -45,6 +45,7 @@ Readebble.sendHeadlines = function() { Readebble.sendStory = function(story) { var maxStoryBuffer = Readebble.bufferSize - 32; + appMessageQueue.send({type:TYPE.STORY, method:METHOD.SIZE, index:story.length}); for (var i = 0; i <= Math.floor(story.length/maxStoryBuffer); i++) { appMessageQueue.send({type:TYPE.STORY, method:METHOD.DATA, title:story.substring(i * maxStoryBuffer, i * maxStoryBuffer + maxStoryBuffer)}); } diff --git a/src/layers/progress_bar.c b/src/layers/progress_bar.c index 449bfe3..11dd717 100644 --- a/src/layers/progress_bar.c +++ b/src/layers/progress_bar.c @@ -2,7 +2,6 @@ #include "layers/progress_bar.h" typedef struct _ProgressBarData { - //Layer *layer; uint8_t progress; ProgressBarLayerUpdateProc update_proc; GColor complete; @@ -12,11 +11,10 @@ typedef struct _ProgressBarData { static void progress_bar_layer_update_proc(ProgressBarLayer *progress_bar_layer, GContext *ctx); float math_sqrt(const float num); - ProgressBarLayer * progress_bar_layer_create_fullscreen(Window * window) { - GRect bounds = layer_get_bounds(window_get_root_layer(window)); + GRect window_bounds = layer_get_bounds(window_get_root_layer(window)); GPoint start = GPoint(0, STATUS_BAR_LAYER_HEIGHT - 2); - int16_t width = bounds.size.w; + int16_t width = window_bounds.size.w; ProgressBarLayer *progress_bar_layer = progress_bar_layer_create(start, width); @@ -75,8 +73,8 @@ void progress_bar_layer_set_pos(ProgressBarLayer * progress_bar_layer, int16_t y int16_t width = (int16_t)math_sqrt((radius * radius) - (offset * offset)); GRect layer_bounds = (GRect){ - .origin = GPoint((window_bounds.size.w / 2) - width + 4, y), - .size = GSize(width * 2 - 8, 1) + .origin = GPoint((window_bounds.size.w / 2) - width, y), + .size = GSize(width * 2, 1) }; layer_set_frame((Layer *)progress_bar_layer, layer_bounds); } @@ -88,10 +86,6 @@ void progress_bar_layer_set_progress(ProgressBarLayer * progress_bar_layer, uint layer_mark_dirty((Layer *)progress_bar_layer); } -//Layer * progress_bar_layer_get_layer(ProgressBarLayer * progress_bar_layer) { -// return (Layer *)progress_bar_layer; -//} - void progress_bar_layer_set_colors(ProgressBarLayer * progress_bar_layer, GColor complete, GColor remaining) { ProgressBarData *progress_bar_data = (ProgressBarData *)layer_get_data((Layer *)progress_bar_layer); diff --git a/src/layers/progress_bar.h b/src/layers/progress_bar.h index e167262..7bb6f62 100644 --- a/src/layers/progress_bar.h +++ b/src/layers/progress_bar.h @@ -1,7 +1,5 @@ #pragma once -#define PROGRESS_BAR_WINDOW_SIZE (GSize(144, 1)) - typedef Layer ProgressBarLayer; typedef void(* ProgressBarLayerUpdateProc)(ProgressBarLayer *layer, GContext *ctx); @@ -12,12 +10,10 @@ ProgressBarLayer * progress_bar_layer_create(GPoint start, int16_t width); void progress_bar_layer_destroy(ProgressBarLayer * progress_bar_layer); void progress_bar_layer_set_pos(ProgressBarLayer * progress_bar_layer, int16_t y); void progress_bar_layer_set_progress(ProgressBarLayer * progress_bar_layer, uint8_t percent); -//Layer * progress_bar_layer_get_layer(ProgressBarLayer * progress_bar_layer); void progress_bar_layer_set_colors(ProgressBarLayer * progress_bar_layer, GColor complete, GColor remaining); GColor progress_bar_layer_get_complete_color(ProgressBarLayer * progress_bar_layer); GColor progress_bar_layer_get_remaining_color(ProgressBarLayer * progress_bar_layer); void progress_bar_layer_set_update_proc(ProgressBarLayer * progress_bar_layer, ProgressBarLayerUpdateProc update_proc); - void progress_bar_layer_stretch(ProgressBarLayer * progress_bar_layer); ProgressBarLayer * progress_bar_layer_create_fullscreen(Window * window); diff --git a/src/layers/title_bar.c b/src/layers/title_bar.c new file mode 100644 index 0000000..449d2b2 --- /dev/null +++ b/src/layers/title_bar.c @@ -0,0 +1,162 @@ +#include +#include "layers/title_bar.h" + +typedef struct TitleBarData { + TitleBarLayerUpdateProc update_proc; + GColor foreground; + GColor background; + TextLayer * text_layer; +} TitleBarData; + +static void title_bar_layer_update_proc(TitleBarLayer *title_bar_layer, GContext *ctx); +void title_bar_layer_centre_text_vertically(TitleBarLayer * title_bar_layer); + +TitleBarLayer * title_bar_layer_create_fullscreen(Window * window) { + GRect window_bounds = layer_get_bounds(window_get_root_layer(window)); + + GRect layer_bounds = (GRect){ + .origin = GPoint(0, 0), + .size = GSize(window_bounds.size.w, TITLE_BAR_DEFAULT_HEIGHT) + }; + + TitleBarLayer *title_bar_layer = title_bar_layer_create(layer_bounds); + + Layer *window_layer = window_get_root_layer(window); + layer_add_child(window_layer, title_bar_layer_get_layer(title_bar_layer)); + + TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); + text_layer_enable_screen_text_flow_and_paging(title_bar_data->text_layer, 2); + title_bar_layer_centre_text_vertically(title_bar_layer); + + return title_bar_layer; +} + +TitleBarLayer * title_bar_layer_create(GRect bounds) { + // Set up the title layer + TitleBarLayer *title_bar_layer = layer_create_with_data(bounds, sizeof(TitleBarData)); + TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); + title_bar_data->foreground = GColorBlack; + title_bar_data->background = GColorWhite; + title_bar_data->update_proc = NULL; + + title_bar_data->text_layer = text_layer_create(bounds); + text_layer_set_text_alignment(title_bar_data->text_layer, GTextAlignmentCenter); + text_layer_set_text_color(title_bar_data->text_layer, GColorBlack); + text_layer_set_background_color(title_bar_data->text_layer, GColorClear); + + layer_add_child((Layer*)title_bar_layer, text_layer_get_layer(title_bar_data->text_layer)); + + layer_set_update_proc(title_bar_layer, title_bar_layer_update_proc); + + return title_bar_layer; +} + +void title_bar_layer_stretch(TitleBarLayer * title_bar_layer) { + TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); + GRect window_bounds = layer_get_bounds(window_get_root_layer(layer_get_window((Layer *)title_bar_layer))); + GRect layer_bounds = layer_get_bounds((Layer *)title_bar_layer); + + layer_bounds.origin.x = 0; + layer_bounds.size.w = window_bounds.size.w; + layer_set_frame((Layer *)title_bar_layer, layer_bounds); + + layer_set_frame(text_layer_get_layer(title_bar_data->text_layer), layer_bounds); + title_bar_layer_centre_text_vertically(title_bar_layer); +} + +void title_bar_layer_add_to_window(TitleBarLayer * title_bar_layer, Window *window) { + TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); + layer_add_child(window_get_root_layer(window), (Layer *)title_bar_layer); + text_layer_enable_screen_text_flow_and_paging(title_bar_data->text_layer, 2); + title_bar_layer_centre_text_vertically(title_bar_layer); +} + +void title_bar_layer_destroy(TitleBarLayer * title_bar_layer) { + TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); + + // Remove text layer + layer_remove_child_layers(text_layer_get_layer(title_bar_data->text_layer)); + layer_remove_from_parent(text_layer_get_layer(title_bar_data->text_layer)); + text_layer_destroy(title_bar_data->text_layer); + + // Disconnect from other layers + layer_remove_child_layers((Layer *)title_bar_layer); + layer_remove_from_parent((Layer *)title_bar_layer); + + // Free all memory + layer_destroy((Layer *)title_bar_layer); +} + +void title_bar_layer_set_height(TitleBarLayer * title_bar_layer, int16_t height) { + TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); + GRect window_bounds = layer_get_bounds(window_get_root_layer(layer_get_window((Layer *)title_bar_layer))); + + GRect layer_bounds = (GRect){ + .origin = GPoint(0, 0), + .size = GSize(window_bounds.size.w, height) + }; + layer_set_frame((Layer *)title_bar_layer, layer_bounds); + layer_set_frame(text_layer_get_layer(title_bar_data->text_layer), layer_bounds); + title_bar_layer_centre_text_vertically(title_bar_layer); +} + +void title_bar_layer_set_colors(TitleBarLayer * title_bar_layer, GColor foreground, GColor background) { + TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); + + text_layer_set_text_color(title_bar_data->text_layer, foreground); + title_bar_data->foreground = foreground; + title_bar_data->background = background; + layer_mark_dirty((Layer *)title_bar_layer); +} + +GColor title_bar_layer_get_foreground_color(TitleBarLayer * title_bar_layer) { + TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); + + return title_bar_data->foreground; +} + +GColor title_bar_layer_get_background_color(TitleBarLayer * title_bar_layer) { + TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); + + return title_bar_data->background; +} + +void title_bar_layer_set_update_proc(TitleBarLayer * title_bar_layer, TitleBarLayerUpdateProc update_proc) { + TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); + + title_bar_data->update_proc = update_proc; +} + +static void title_bar_layer_update_proc(Layer *layer, GContext *ctx) { + TitleBarData *title_bar_data = (TitleBarData *)layer_get_data(layer); + + if (title_bar_data->update_proc != NULL) { + title_bar_data->update_proc((TitleBarLayer *)layer, ctx); + } + else { + GRect bounds = layer_get_bounds(layer); + graphics_context_set_fill_color(ctx, title_bar_data->background); + graphics_fill_rect(ctx, bounds, 0, GCornerNone); + } +} + +void title_bar_layer_set_text(TitleBarLayer * title_bar_layer, const char * text) { + TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); + + text_layer_set_text(title_bar_data->text_layer, text); + title_bar_layer_centre_text_vertically(title_bar_layer); +} + +void title_bar_layer_centre_text_vertically(TitleBarLayer * title_bar_layer) { + TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); + + GRect title_bar_bounds = layer_get_bounds((Layer *)title_bar_layer); + GRect text_bounds = layer_get_bounds(text_layer_get_layer(title_bar_data->text_layer)); + GSize text_size = text_layer_get_content_size(title_bar_data->text_layer); + + text_bounds.origin.y = (title_bar_bounds.size.h - text_size.h) / 2; + + layer_set_frame(text_layer_get_layer(title_bar_data->text_layer), text_bounds); +} + + diff --git a/src/layers/title_bar.h b/src/layers/title_bar.h new file mode 100644 index 0000000..0296218 --- /dev/null +++ b/src/layers/title_bar.h @@ -0,0 +1,22 @@ +#pragma once + +#define TITLE_BAR_DEFAULT_HEIGHT (STATUS_BAR_LAYER_HEIGHT + 12) +#define TITLE_BAR_DEFAULT_WIDTH PBL_IF_RECT_ELSE(144, 180) + +typedef Layer TitleBarLayer; +typedef void(* TitleBarLayerUpdateProc)(TitleBarLayer *layer, GContext *ctx); + +#define title_bar_layer_get_layer(layer) (Layer *)layer +#define title_bar_layer_destroy_safe(layer) if (layer != NULL) { title_bar_layer_destroy(layer); layer = NULL; } + +TitleBarLayer * title_bar_layer_create(GRect bounds); +void title_bar_layer_destroy(TitleBarLayer * title_bar_layer); +void title_bar_layer_set_height(TitleBarLayer * title_bar_layer, int16_t height); +void title_bar_layer_set_colors(TitleBarLayer * title_bar_layer, GColor foreground, GColor background); +GColor title_bar_layer_get_foreground_color(TitleBarLayer * title_bar_layer); +GColor title_bar_layer_get_background_color(TitleBarLayer * title_bar_layer); +void title_bar_layer_set_update_proc(TitleBarLayer * title_bar_layer, TitleBarLayerUpdateProc update_proc); +void title_bar_layer_stretch(TitleBarLayer * title_bar_layer); +TitleBarLayer * title_bar_layer_create_fullscreen(Window * window); +void title_bar_layer_set_text(TitleBarLayer * title_bar_layer, const char * text); + diff --git a/src/rss.c b/src/rss.c index 1854d88..207490e 100644 --- a/src/rss.c +++ b/src/rss.c @@ -101,7 +101,13 @@ static void timer_callback(void *data) { DictionaryIterator *iter; app_message_outbox_begin(&iter); dict_write_uint8(iter, APP_KEY_METHOD, KEY_METHOD_BUFFERSIZE); - dict_write_uint32(iter, APP_KEY_INDEX, app_message_inbox_size_maximum()); + //dict_write_uint32(iter, APP_KEY_INDEX, app_message_inbox_size_maximum()); + // Reducing the size of the buffer allows the story to be sent in chunks + uint32_t buffersize = 128; + if (buffersize > app_message_inbox_size_maximum()) { + buffersize = app_message_inbox_size_maximum(); + } + dict_write_uint32(iter, APP_KEY_INDEX, buffersize); dict_write_end(iter); app_message_outbox_send(); } diff --git a/src/story.c b/src/story.c index ee41642..0e71779 100644 --- a/src/story.c +++ b/src/story.c @@ -9,8 +9,15 @@ #define STORY_MAX_LEN 2000 static char story[STORY_MAX_LEN]; +static uint32_t story_size; +static uint32_t story_loaded; +static uint8_t progress = 0; + +void story_update_progress(); void story_init(void) { + story_size = 0u; + story_loaded = 0u; win_story_init(); } @@ -22,13 +29,25 @@ void story_in_received_handler(DictionaryIterator *iter) { Tuple *tuple = dict_find(iter, APP_KEY_METHOD); if (!tuple) return; switch (tuple->value->uint8) { + case KEY_METHOD_SIZE: + tuple = dict_find(iter, APP_KEY_INDEX); + if (!tuple) break; + story_size = tuple->value->uint32; + progress = (story_size == 0 ? 100 : 0); + break; case KEY_METHOD_DATA: tuple = dict_find(iter, APP_KEY_TITLE); if (!tuple) break; - if (strlen(story) + tuple->length < STORY_MAX_LEN) + if (strlen(story) + tuple->length < STORY_MAX_LEN) { strcat(story, tuple->value->cstring); + story_loaded += tuple->length; + progress = (story_loaded * 100) / story_size; + story_update_progress(); + LOG("loaded: %u", (unsigned int)story_loaded); + } break; case KEY_METHOD_READY: + progress = 100; win_story_reload_data_and_mark_dirty(); break; } @@ -40,6 +59,8 @@ char* story_get() { void story_request() { story[0] = '\0'; + story_size = 0u; + story_loaded = 0u; DictionaryIterator *iter; app_message_outbox_begin(&iter); dict_write_uint8(iter, APP_KEY_METHOD, KEY_METHOD_REQUESTSTORY); @@ -47,3 +68,12 @@ void story_request() { dict_write_end(iter); app_message_outbox_send(); } + +void story_update_progress() { + win_story_update_progress(); +} + +uint8_t story_progress() { + return progress; +} + diff --git a/src/story.h b/src/story.h index 5fc29c4..bcc33fd 100644 --- a/src/story.h +++ b/src/story.h @@ -8,3 +8,5 @@ void story_in_received_handler(DictionaryIterator *iter); char* story_get(); void story_free(); void story_request(); +uint8_t story_progress(); + diff --git a/src/windows/win-headlines.c b/src/windows/win-headlines.c index 1f19b4e..452bd8f 100644 --- a/src/windows/win-headlines.c +++ b/src/windows/win-headlines.c @@ -7,6 +7,7 @@ #include "rss.h" #include "win-story.h" #include "layers/progress_bar.h" +#include "layers/title_bar.h" #define TEXT_BORDER_INSET (16) @@ -26,7 +27,7 @@ static Window *window = NULL; static MenuLayer *menu_layer = NULL; static ProgressBarLayer *s_progress_bar_layer; #ifdef PBL_SDK_3 -static TextLayer *s_status_bar; +static TitleBarLayer *s_status_bar; #endif void win_headlines_init(void) { @@ -99,8 +100,8 @@ static void menu_select_long_callback(struct MenuLayer *menu_layer, MenuIndex *c } static void window_load(Window *window) { - Layer *window_layer = window_get_root_layer(window); - GRect bounds = layer_get_bounds(window_layer); + //Layer *window_layer = window_get_root_layer(window); + //GRect bounds = layer_get_bounds(window_layer); menu_layer = menu_layer_create_fullscreen(window); menu_layer_set_callbacks(menu_layer, NULL, (MenuLayerCallbacks) { @@ -119,21 +120,9 @@ static void window_load(Window *window) { #ifdef PBL_SDK_3 // Set up the status bar if it's needed - GRect bar_bounds = bounds; - bar_bounds.size.h = STATUS_BAR_LAYER_HEIGHT + 12; - s_status_bar = text_layer_create(bar_bounds); - text_layer_set_text_alignment(s_status_bar, GTextAlignmentCenter); - text_layer_set_colors(s_status_bar, GColorBlack, GColorPastelYellow); - text_layer_set_text(s_status_bar, subscriptions_get_current()->title); - layer_add_child(window_layer, text_layer_get_layer(s_status_bar)); - text_layer_enable_screen_text_flow_and_paging(s_status_bar, 2); - GSize size = text_layer_get_content_size(s_status_bar); - size.h += 4; - size.w = bounds.size.w; - if (size.h > STATUS_BAR_SIZE_MAX) { - size.h = STATUS_BAR_SIZE_MAX; - } - text_layer_set_size(s_status_bar, size); + s_status_bar = title_bar_layer_create_fullscreen(window); + title_bar_layer_set_colors(s_status_bar, GColorBlack, GColorPastelYellow); + title_bar_layer_set_text(s_status_bar, subscriptions_get_current()->title); #endif #ifdef PBL_COLOR @@ -143,8 +132,8 @@ static void window_load(Window *window) { // Set up the progress layer s_progress_bar_layer = progress_bar_layer_create_fullscreen(window); - - progress_bar_layer_set_pos(s_progress_bar_layer, STATUS_BAR_LAYER_HEIGHT); + progress_bar_layer_set_pos(s_progress_bar_layer, TITLE_BAR_DEFAULT_HEIGHT); + progress_bar_layer_set_colors(s_progress_bar_layer, GColorOrange, GColorWhite); } static void window_unload(Window *window) { @@ -152,7 +141,7 @@ static void window_unload(Window *window) { #ifdef PBL_SDK_3 // Destroy the status bar if there is one - text_layer_destroy(s_status_bar); + title_bar_layer_destroy(s_status_bar); #endif // Destroy the progress bar diff --git a/src/windows/win-story.c b/src/windows/win-story.c index 63ac0bd..94035ce 100644 --- a/src/windows/win-story.c +++ b/src/windows/win-story.c @@ -6,6 +6,10 @@ #include "headlines.h" #include "subscriptions.h" #include "rss.h" +#include "layers/progress_bar.h" + +#define TITLE_LAYER_PAD (8) +#define STORY_LAYER_PAD (8) static void select_long_click_handler(ClickRecognizerRef recognizer, void *context); static void click_config_provider(void *context); @@ -16,6 +20,7 @@ static Window *window = NULL; static ScrollLayer *scroll_layer = NULL; static TextLayer *title_text_layer = NULL; static TextLayer *story_text_layer = NULL; +static ProgressBarLayer *progress_bar_layer = NULL; void win_story_init(void) { window = window_create(); @@ -37,22 +42,33 @@ void win_story_deinit(void) { void win_story_reload_data_and_mark_dirty(void) { if (!window_is_loaded(window)) return; - text_layer_set_text(story_text_layer, story_get()); + GRect window_bounds = layer_get_bounds(window_get_root_layer(window)); + GRect title_layer_bounds = layer_get_bounds(text_layer_get_layer(title_text_layer)); - GSize title_layer_size = text_layer_get_content_size(title_text_layer); - GSize story_layer_size = text_layer_get_content_size(story_text_layer); + text_layer_set_text(story_text_layer, story_get()); - title_layer_size.h += 8; - story_layer_size.h += 8; + GSize story_layer_size = window_bounds.size; + story_layer_size.h *= 10; + text_layer_set_size(story_text_layer, story_layer_size); - text_layer_set_size(title_text_layer, title_layer_size); + story_layer_size = text_layer_get_content_size(story_text_layer); + story_layer_size.w = window_bounds.size.w; + story_layer_size.h += STORY_LAYER_PAD; text_layer_set_size(story_text_layer, story_layer_size); - scroll_layer_set_content_size(scroll_layer, GSize(144, title_layer_size.h + story_layer_size.h)); + scroll_layer_set_content_size(scroll_layer, GSize(window_bounds.size.w, story_layer_size.h + title_layer_bounds.size.h)); + scroll_layer_set_paging(scroll_layer, true); + + progress_bar_layer_set_progress(progress_bar_layer, 100); scroll_layer_mark_dirty(scroll_layer); } +void win_story_update_progress(void) { + if (!window_is_loaded(window)) return; + progress_bar_layer_set_progress(progress_bar_layer, story_progress()); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // static void select_long_click_handler(ClickRecognizerRef recognizer, void *context) { @@ -64,7 +80,23 @@ static void click_config_provider(void *context) { } static void window_load(Window *window) { - window_set_background_color(window, settings()->story_font_color ? GColorBlack : GColorWhite); + //window_set_background_color(window, settings()->story_font_color ? GColorBlack : GColorWhite); + window_set_background_color(window, GColorWhite); + GRect window_bounds = layer_get_bounds(window_get_root_layer(window)); + + story_text_layer = text_layer_create(window_bounds); + text_layer_set_colors(story_text_layer, GColorBlack, GColorWhite); + text_layer_set_font(story_text_layer, fonts_get_system_font(settings()->story_font_size ? FONT_KEY_GOTHIC_24 : FONT_KEY_GOTHIC_14)); + text_layer_set_text_alignment(story_text_layer, GTextAlignmentCenter); + text_layer_set_text(story_text_layer, "Loading..."); + + + title_text_layer = text_layer_create(window_bounds); + text_layer_set_colors(title_text_layer, GColorBlack, GColorPastelYellow); + text_layer_set_font(title_text_layer, fonts_get_system_font(settings()->story_font_size ? FONT_KEY_GOTHIC_24_BOLD : FONT_KEY_GOTHIC_14_BOLD)); + text_layer_set_text_alignment(title_text_layer, GTextAlignmentCenter); + text_layer_set_text(title_text_layer, headlines_get_current()->title); + scroll_layer = scroll_layer_create_fullscreeen(window); scroll_layer_set_click_config_onto_window(scroll_layer, window); @@ -73,34 +105,80 @@ static void window_load(Window *window) { }); scroll_layer_add_to_window(scroll_layer, window); - title_text_layer = text_layer_create(GRect(3, -2, 140, 96)); - text_layer_set_colors(title_text_layer, settings()->story_font_color ? GColorWhite : GColorBlack, GColorClear); - text_layer_set_font(title_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD)); - text_layer_set_text(title_text_layer, headlines_get_current()->title); + scroll_layer_add_child(scroll_layer, text_layer_get_layer(story_text_layer)); + scroll_layer_add_child(scroll_layer, text_layer_get_layer(title_text_layer)); - GSize title_layer_size = text_layer_get_content_size(title_text_layer); - title_layer_size.h += 8; + text_layer_enable_screen_text_flow_and_paging(story_text_layer, 2); + text_layer_enable_screen_text_flow_and_paging(title_text_layer, 2); + GSize title_layer_size = window_bounds.size; + title_layer_size.h *= 10; + text_layer_set_size(title_text_layer, title_layer_size); + title_layer_size = text_layer_get_content_size(title_text_layer); + title_layer_size.w = window_bounds.size.w; + title_layer_size.h += TITLE_LAYER_PAD; text_layer_set_size(title_text_layer, title_layer_size); - story_text_layer = text_layer_create(GRect(3, title_layer_size.h, 140, 1024)); - text_layer_set_colors(story_text_layer, settings()->story_font_color ? GColorWhite : GColorBlack, GColorClear); - text_layer_set_font(story_text_layer, fonts_get_system_font(settings()->story_font_size ? FONT_KEY_GOTHIC_24_BOLD : FONT_KEY_GOTHIC_18_BOLD)); - text_layer_set_text(story_text_layer, "Loading..."); - - GSize story_layer_size = text_layer_get_content_size(story_text_layer); - story_layer_size.h = story_layer_size.h + 8; + GSize story_layer_size = window_bounds.size; + story_layer_size.h *= 10; + text_layer_set_size(story_text_layer, story_layer_size); + story_layer_size = text_layer_get_content_size(story_text_layer); + story_layer_size.w = window_bounds.size.w; + story_layer_size.h += STORY_LAYER_PAD; text_layer_set_size(story_text_layer, story_layer_size); - scroll_layer_set_content_size(scroll_layer, GSize(144, title_layer_size.h + story_layer_size.h)); + GRect story_layer_frame = layer_get_frame(text_layer_get_layer(story_text_layer)); + story_layer_frame.origin.y = title_layer_size.h; + layer_set_frame((Layer*)story_text_layer, story_layer_frame); + text_layer_enable_screen_text_flow_and_paging(story_text_layer, 2); - scroll_layer_add_child(scroll_layer, text_layer_get_layer(title_text_layer)); - scroll_layer_add_child(scroll_layer, text_layer_get_layer(story_text_layer)); + GSize scroll_layer_size = window_bounds.size; + scroll_layer_size.h = title_layer_size.h + story_layer_size.h; + scroll_layer_set_content_size(scroll_layer, scroll_layer_size); + + scroll_layer_set_paging(scroll_layer, true); + + + + //text_layer_set_colors(title_text_layer, settings()->story_font_color ? GColorWhite : GColorBlack, GColorPastelYellow); + //text_layer_set_font(title_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD)); + //text_layer_set_text(title_text_layer, headlines_get_current()->title); + + //scroll_layer_add_child(scroll_layer, text_layer_get_layer(title_text_layer)); + //text_layer_enable_screen_text_flow_and_paging(title_text_layer, 2); + + //GSize title_layer_size = text_layer_get_content_size(title_text_layer); + //title_layer_size.w = window_bounds.size.w; + //title_layer_size.h += 8; + + //text_layer_set_size(title_text_layer, title_layer_size); + + //GRect text_layer_bounds = window_bounds; + //text_layer_bounds.origin.y = title_layer_size.h; + //story_text_layer = text_layer_create(text_layer_bounds); + //text_layer_set_colors(story_text_layer, settings()->story_font_color ? GColorWhite : GColorBlack, GColorClear); + + + //GSize story_layer_size = text_layer_get_content_size(story_text_layer); + //story_layer_size.h = story_layer_size.h + 8; + //story_layer_size.h = window_bounds.size.h; + //text_layer_set_size(story_text_layer, story_layer_size); + + // Set up the progress layer + progress_bar_layer = progress_bar_layer_create_fullscreen(window); + progress_bar_layer_set_pos(progress_bar_layer, title_layer_size.h); + progress_bar_layer_set_colors(progress_bar_layer, GColorOrange, GColorWhite); + progress_bar_layer_set_progress(progress_bar_layer, 0); + scroll_layer_add_child(scroll_layer, progress_bar_layer_get_layer(progress_bar_layer)); } static void window_unload(Window *window) { text_layer_destroy_safe(title_text_layer); text_layer_destroy_safe(story_text_layer); scroll_layer_destroy_safe(scroll_layer); + + // Destroy the progress bar + progress_bar_layer_destroy(progress_bar_layer); } + diff --git a/src/windows/win-story.h b/src/windows/win-story.h index ca1fbc1..5a45d1f 100644 --- a/src/windows/win-story.h +++ b/src/windows/win-story.h @@ -4,3 +4,4 @@ void win_story_init(void); void win_story_push(void); void win_story_deinit(void); void win_story_reload_data_and_mark_dirty(void); +void win_story_update_progress(void); From 924082bd13e9b60584ffe4ef14dd8234214f44dd Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Fri, 8 Jan 2016 21:17:03 +0000 Subject: [PATCH 06/13] Fix subscription list on non-round screens Fix the way subscriptions are shown on aplite and basalt emulators. Tweak the status bar location, centering of the menu selection and colours to suit each platform. --- src/windows/win-subscriptions.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/windows/win-subscriptions.c b/src/windows/win-subscriptions.c index e193182..1a48208 100644 --- a/src/windows/win-subscriptions.c +++ b/src/windows/win-subscriptions.c @@ -26,8 +26,8 @@ int menu_item_settings_pos(); static Window *window = NULL; static MenuLayer *menu_layer = NULL; -#ifdef PBL_SDK_3 static StatusBarLayer *s_status_bar; +#ifdef PBL_ROUND static TextLayer *s_lower_bar; #endif @@ -97,7 +97,9 @@ static void menu_draw_header_callback(GContext *ctx, const Layer *cell_layer, ui static void menu_draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *callback_context) { if (cell_index->row == menu_item_settings_pos()) { +#ifdef PBL_COLOR graphics_context_set_text_color(ctx, GColorBlue); +#endif menu_cell_basic_draw(ctx, cell_layer, "Settings", NULL, NULL); } else if (subscriptions_get_error()) { //graphics_context_set_text_color(ctx, GColorBlack); @@ -124,7 +126,9 @@ static void menu_select_long_callback(struct MenuLayer *menu_layer, MenuIndex *c static void window_load(Window *window) { Layer *window_layer = window_get_root_layer(window); +#ifdef PBL_ROUND GRect bounds = layer_get_bounds(window_layer); +#endif menu_layer = menu_layer_create_fullscreen(window); menu_layer_set_callbacks(menu_layer, NULL, (MenuLayerCallbacks) { @@ -140,12 +144,12 @@ static void window_load(Window *window) { menu_layer_set_click_config_onto_window(menu_layer, window); menu_layer_add_to_window(menu_layer, window); -#ifdef PBL_SDK_3 // Set up the status bar if it's needed s_status_bar = status_bar_layer_create(); layer_add_child(window_layer, status_bar_layer_get_layer(s_status_bar)); status_bar_layer_set_colors(s_status_bar, GColorWhite, GColorBlack); +#ifdef PBL_ROUND // Set up the lower message bar const GEdgeInsets message_insets = {.top = bounds.size.h - STATUS_BAR_LAYER_HEIGHT}; s_lower_bar = text_layer_create(grect_inset(bounds, message_insets)); @@ -153,6 +157,11 @@ static void window_load(Window *window) { text_layer_set_colors(s_lower_bar, GColorBlack, GColorWhite); text_layer_set_text(s_lower_bar, ""); layer_add_child(window_layer, text_layer_get_layer(s_lower_bar)); +#else + GRect menu_bounds = layer_get_bounds(menu_layer_get_layer(menu_layer)); + menu_bounds.origin.y += STATUS_BAR_LAYER_HEIGHT; + menu_bounds.size.h -= STATUS_BAR_LAYER_HEIGHT * 2; + layer_set_bounds(menu_layer_get_layer(menu_layer), menu_bounds); #endif #ifdef PBL_COLOR @@ -164,9 +173,9 @@ static void window_load(Window *window) { static void window_unload(Window *window) { menu_layer_destroy_safe(menu_layer); -#ifdef PBL_SDK_3 // Destroy the status bar if there is one status_bar_layer_destroy(s_status_bar); +#ifdef PBL_ROUND text_layer_destroy(s_lower_bar); #endif } From 8833056f74d6fa050e91fd8d3d5b88988a135b8f Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Fri, 8 Jan 2016 21:26:09 +0000 Subject: [PATCH 07/13] Fix settings rendering on non-round screens --- src/windows/win-settings.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/windows/win-settings.c b/src/windows/win-settings.c index ed1007e..c3fd75a 100644 --- a/src/windows/win-settings.c +++ b/src/windows/win-settings.c @@ -98,13 +98,7 @@ static void menu_draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuI strncpy(value, settings()->story_font_color ? "White": "Black", sizeof(value)); break; } -#ifdef PBL_RECT - graphics_context_set_text_color(ctx, GColorBlack); - graphics_draw_text(ctx, settings_labels[cell_index->row], fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(4, 2, 136, 28), GTextOverflowModeTrailingEllipsis, GTextAlignmentLeft, NULL); - graphics_draw_text(ctx, value, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), GRect(4, 7, 134, 24), GTextOverflowModeTrailingEllipsis, GTextAlignmentRight, NULL); -#else menu_cell_basic_draw(ctx, cell_layer, settings_labels[cell_index->row], value, NULL); -#endif } static void menu_select_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context) { @@ -124,7 +118,9 @@ static void menu_select_callback(struct MenuLayer *menu_layer, MenuIndex *cell_i static void window_load(Window *window) { Layer *window_layer = window_get_root_layer(window); +#ifdef PBL_ROUND GRect bounds = layer_get_bounds(window_layer); +#endif menu_layer = menu_layer_create_fullscreen(window); menu_layer_set_callbacks(menu_layer, NULL, (MenuLayerCallbacks) { @@ -139,12 +135,12 @@ static void window_load(Window *window) { menu_layer_set_click_config_onto_window(menu_layer, window); menu_layer_add_to_window(menu_layer, window); -#ifdef PBL_SDK_3 // Set up the status bar if it's needed s_status_bar = status_bar_layer_create(); layer_add_child(window_layer, status_bar_layer_get_layer(s_status_bar)); status_bar_layer_set_colors(s_status_bar, GColorWhite, GColorBlack); +#ifdef PBL_ROUND // Set up the lower message bar const GEdgeInsets message_insets = {.top = bounds.size.h - STATUS_BAR_LAYER_HEIGHT}; s_lower_bar = text_layer_create(grect_inset(bounds, message_insets)); @@ -152,6 +148,11 @@ static void window_load(Window *window) { text_layer_set_colors(s_lower_bar, GColorBlack, GColorWhite); text_layer_set_text(s_lower_bar, ""); layer_add_child(window_layer, text_layer_get_layer(s_lower_bar)); +#else + GRect menu_bounds = layer_get_bounds(menu_layer_get_layer(menu_layer)); + menu_bounds.origin.y += STATUS_BAR_LAYER_HEIGHT; + menu_bounds.size.h -= STATUS_BAR_LAYER_HEIGHT * 2; + layer_set_bounds(menu_layer_get_layer(menu_layer), menu_bounds); #endif #ifdef PBL_COLOR From 0722a14e9c72c483cb85da7a4870534cd6ea5890 Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Tue, 12 Jan 2016 22:28:49 +0000 Subject: [PATCH 08/13] Increase configurability of colours and text sizes Move colour configuration into the settings file. Define a structure for setting up colour schemes. Set colours when a window appears (as opposed to when it loads). Define suitable colours for both colour and B&W displays. --- src/js/src/appmessagequeue.js | 3 +- src/layers/progress_bar.c | 8 ++ src/layers/title_bar.c | 5 ++ src/layers/title_bar.h | 4 +- src/settings.c | 141 +++++++++++++++++++++++++++++++- src/settings.h | 42 +++++++++- src/windows/win-headlines.c | 42 ++++++---- src/windows/win-settings.c | 44 ++++++---- src/windows/win-story.c | 26 ++++-- src/windows/win-subscriptions.c | 40 ++++++--- 10 files changed, 298 insertions(+), 57 deletions(-) diff --git a/src/js/src/appmessagequeue.js b/src/js/src/appmessagequeue.js index 700cbaf..d985c4a 100644 --- a/src/js/src/appmessagequeue.js +++ b/src/js/src/appmessagequeue.js @@ -24,7 +24,8 @@ var appMessageQueue = { appMessageQueue.working = false; appMessageQueue.send(); }; - var nack = function() { + var nack = function(data) { + console.log("Error: " + JSON.stringify(data)); appMessageQueue.numTries++; appMessageQueue.working = false; appMessageQueue.send(); diff --git a/src/layers/progress_bar.c b/src/layers/progress_bar.c index 11dd717..dfbc99f 100644 --- a/src/layers/progress_bar.c +++ b/src/layers/progress_bar.c @@ -9,7 +9,9 @@ typedef struct _ProgressBarData { } ProgressBarData; static void progress_bar_layer_update_proc(ProgressBarLayer *progress_bar_layer, GContext *ctx); +#ifdef PBL_ROUND float math_sqrt(const float num); +#endif ProgressBarLayer * progress_bar_layer_create_fullscreen(Window * window) { GRect window_bounds = layer_get_bounds(window_get_root_layer(window)); @@ -68,9 +70,13 @@ void progress_bar_layer_destroy(ProgressBarLayer * progress_bar_layer) { void progress_bar_layer_set_pos(ProgressBarLayer * progress_bar_layer, int16_t y) { GRect window_bounds = layer_get_bounds(window_get_root_layer(layer_get_window((Layer *)progress_bar_layer))); +#ifdef PBL_ROUND float radius = ((float)window_bounds.size.h / 2.0); float offset = (radius - (float)y); int16_t width = (int16_t)math_sqrt((radius * radius) - (offset * offset)); +#else + int16_t width = window_bounds.size.w / 2; +#endif GRect layer_bounds = (GRect){ .origin = GPoint((window_bounds.size.w / 2) - width, y), @@ -131,6 +137,7 @@ static void progress_bar_layer_update_proc(Layer *layer, GContext *ctx) { } } +#ifdef PBL_ROUND // See https://forums.getpebble.com/discussion/comment/79122/#Comment_79122 float math_sqrt(const float num) { const uint MAX_STEPS = 40; @@ -145,4 +152,5 @@ float math_sqrt(const float num) { } return answer; } +#endif diff --git a/src/layers/title_bar.c b/src/layers/title_bar.c index 449d2b2..8c1e197 100644 --- a/src/layers/title_bar.c +++ b/src/layers/title_bar.c @@ -100,6 +100,11 @@ void title_bar_layer_set_height(TitleBarLayer * title_bar_layer, int16_t height) title_bar_layer_centre_text_vertically(title_bar_layer); } +int16_t title_bar_layer_get_height(TitleBarLayer * title_bar_layer) { + GRect layer_bounds = layer_get_bounds(title_bar_layer_get_layer(title_bar_layer)); + return layer_bounds.size.h; +} + void title_bar_layer_set_colors(TitleBarLayer * title_bar_layer, GColor foreground, GColor background) { TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); diff --git a/src/layers/title_bar.h b/src/layers/title_bar.h index 0296218..0a231ce 100644 --- a/src/layers/title_bar.h +++ b/src/layers/title_bar.h @@ -1,6 +1,7 @@ #pragma once -#define TITLE_BAR_DEFAULT_HEIGHT (STATUS_BAR_LAYER_HEIGHT + 12) +#define TITLE_BAR_DEFAULT_HEIGHT PBL_IF_ROUND_ELSE ((STATUS_BAR_LAYER_HEIGHT + 12), (STATUS_BAR_LAYER_HEIGHT + 24)) + #define TITLE_BAR_DEFAULT_WIDTH PBL_IF_RECT_ELSE(144, 180) typedef Layer TitleBarLayer; @@ -12,6 +13,7 @@ typedef void(* TitleBarLayerUpdateProc)(TitleBarLayer *layer, GContext *ctx); TitleBarLayer * title_bar_layer_create(GRect bounds); void title_bar_layer_destroy(TitleBarLayer * title_bar_layer); void title_bar_layer_set_height(TitleBarLayer * title_bar_layer, int16_t height); +int16_t title_bar_layer_get_height(TitleBarLayer * title_bar_layer); void title_bar_layer_set_colors(TitleBarLayer * title_bar_layer, GColor foreground, GColor background); GColor title_bar_layer_get_foreground_color(TitleBarLayer * title_bar_layer); GColor title_bar_layer_get_background_color(TitleBarLayer * title_bar_layer); diff --git a/src/settings.c b/src/settings.c index 7ecfe41..e129d17 100644 --- a/src/settings.c +++ b/src/settings.c @@ -3,11 +3,100 @@ #include "persist.h" #include "windows/win-settings.h" +const char * font_size_string[] = { + "Small", + "Medium", + "Large" +}; + +const char * font_color_string[] = { + "Dark", + "Light" +}; + +const char * headlines_font_size_value[] = { + FONT_KEY_GOTHIC_14, + FONT_KEY_GOTHIC_18, + FONT_KEY_GOTHIC_24 +}; + +const char * story_body_font_size_value[] = { + FONT_KEY_GOTHIC_14, + FONT_KEY_GOTHIC_18, + FONT_KEY_GOTHIC_24 +}; + +const char * story_title_font_size_value[] = { + FONT_KEY_GOTHIC_14_BOLD, + FONT_KEY_GOTHIC_18_BOLD, + FONT_KEY_GOTHIC_24_BOLD +}; + Settings _settings = { .headlines_font_size = FONT_SIZE_SMALL, .story_font_size = FONT_SIZE_SMALL, - .story_font_color = FONT_COLOR_WHITE, + .story_font_color = FONT_COLOR_LIGHT, +}; + +#ifdef PBL_COLOR +static const InterfaceColors s_interface_colors[] = { + // Dark + { + .main_background = {GColorBlackARGB8}, + .main_text = {GColorWhiteARGB8}, + .inverted_text = {GColorBlackARGB8}, + .selection_highlight = {GColorPastelYellowARGB8}, + .title_bar_background = {GColorOrangeARGB8}, + .title_bar_text = {GColorWhiteARGB8}, + .progress_bar_complete = {GColorPastelYellowARGB8}, + .progress_bar_remaining = {GColorBlackARGB8}, + .settings_text = {GColorCelesteARGB8}, + .settings_inverted_text = {GColorBlueARGB8} + }, + // Light + { + .main_background = {GColorWhiteARGB8}, + .main_text = {GColorBlackARGB8}, + .inverted_text = {GColorWhiteARGB8}, + .selection_highlight = {GColorOrangeARGB8}, + .title_bar_background = {GColorPastelYellowARGB8}, + .title_bar_text = {GColorBlackARGB8}, + .progress_bar_complete = {GColorOrangeARGB8}, + .progress_bar_remaining = {GColorWhiteARGB8}, + .settings_text = {GColorBlueARGB8}, + .settings_inverted_text = {GColorCelesteARGB8} + } +}; +#else +static const InterfaceColors s_interface_colors[] = { + // Dark + { + .main_background = {GColorBlackARGB8}, + .main_text = {GColorWhiteARGB8}, + .inverted_text = {GColorBlackARGB8}, + .selection_highlight = {GColorWhiteARGB8}, + .title_bar_background = {GColorBlackARGB8}, + .title_bar_text = {GColorWhiteARGB8}, + .progress_bar_complete = {GColorWhiteARGB8}, + .progress_bar_remaining = {GColorBlackARGB8}, + .settings_text = {GColorWhiteARGB8}, + .settings_inverted_text = {GColorBlackARGB8} + }, + // Light + { + .main_background = {GColorWhiteARGB8}, + .main_text = {GColorBlackARGB8}, + .inverted_text = {GColorWhiteARGB8}, + .selection_highlight = {GColorBlackARGB8}, + .title_bar_background = {GColorWhiteARGB8}, + .title_bar_text = {GColorBlackARGB8}, + .progress_bar_complete = {GColorBlackARGB8}, + .progress_bar_remaining = {GColorWhiteARGB8}, + .settings_text = {GColorBlackARGB8}, + .settings_inverted_text = {GColorWhiteARGB8} + } }; +#endif void settings_init(void) { persist_read_data(KEY_PERSIST_SETTINGS, &_settings, sizeof(_settings)); @@ -22,3 +111,53 @@ void settings_deinit(void) { Settings* settings() { return &_settings; } + +GFont settings_get_story_title_font_size(void) { + return fonts_get_system_font(story_title_font_size_value[_settings.story_font_size]); +} + +GFont settings_get_story_body_font_size(void) { + return fonts_get_system_font(story_body_font_size_value[_settings.story_font_size]); +} + +GFont settings_get_headlines_font_size(void) { + return fonts_get_system_font(headlines_font_size_value[_settings.headlines_font_size]); +} + +const char * settings_get_story_font_size_string(void) { + return font_size_string[_settings.story_font_size]; +} + +const char * settings_get_headlines_font_size_string(void) { + return font_size_string[_settings.headlines_font_size]; +} + +const char * settings_get_story_font_color_string(void) { + return font_color_string[_settings.story_font_color]; +} + +const InterfaceColors * settings_get_colors(void) { + return & s_interface_colors[_settings.story_font_color]; +} + +void settings_bump_headlines_font_size(void) { + _settings.headlines_font_size++; + if (_settings.headlines_font_size >= FONT_SIZE_NUM) { + _settings.headlines_font_size = 0; + } +} + +void settings_bump_story_font_size(void) { + _settings.story_font_size++; + if (_settings.story_font_size >= FONT_SIZE_NUM) { + _settings.story_font_size = 0; + } +} + +void settings_bump_story_font_color(void) { + _settings.story_font_color++; + if (_settings.story_font_color >= FONT_COLOR_NUM) { + _settings.story_font_color = 0; + } +} + diff --git a/src/settings.h b/src/settings.h index 3465da8..13f1c71 100644 --- a/src/settings.h +++ b/src/settings.h @@ -1,13 +1,22 @@ #pragma once typedef enum { + FONT_SIZE_INVALID = -1, + FONT_SIZE_SMALL, + FONT_SIZE_MEDIUM, FONT_SIZE_LARGE, + + FONT_SIZE_NUM } FONT_SIZE; typedef enum { - FONT_COLOR_BLACK, - FONT_COLOR_WHITE, + FONT_COLOR_INVALID = -1, + + FONT_COLOR_DARK, + FONT_COLOR_LIGHT, + + FONT_COLOR_NUM } FONT_COLOR; typedef struct { @@ -16,6 +25,35 @@ typedef struct { FONT_COLOR story_font_color; } Settings; +typedef struct { + GColor main_background; + GColor main_text; + GColor inverted_text; + GColor selection_highlight; + GColor title_bar_background; + GColor title_bar_text; + GColor progress_bar_complete; + GColor progress_bar_remaining; + GColor settings_text; + GColor settings_inverted_text; +} InterfaceColors; + void settings_init(void); void settings_deinit(void); Settings* settings(); + +GFont settings_get_story_title_font_size(void); +GFont settings_get_story_body_font_size(void); +GFont settings_get_headlines_font_size(void); + +const char * settings_get_headlines_font_size_string(void); +const char * settings_get_story_font_size_string(void); +const char * settings_get_story_font_color_string(void); + +void settings_bump_headlines_font_size(void); +void settings_bump_story_font_size(void); +void settings_bump_story_font_color(void); + +const InterfaceColors * settings_get_colors(void); + + diff --git a/src/windows/win-headlines.c b/src/windows/win-headlines.c index 452bd8f..597274f 100644 --- a/src/windows/win-headlines.c +++ b/src/windows/win-headlines.c @@ -22,10 +22,13 @@ static void menu_select_callback(struct MenuLayer *menu_layer, MenuIndex *cell_i static void menu_select_long_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context); static void window_load(Window *window); static void window_unload(Window *window); +static void window_set_colors(Window * window); +static void window_appear(Window *window); static Window *window = NULL; static MenuLayer *menu_layer = NULL; static ProgressBarLayer *s_progress_bar_layer; +static int16_t s_title_bar_height; #ifdef PBL_SDK_3 static TitleBarLayer *s_status_bar; #endif @@ -35,6 +38,7 @@ void win_headlines_init(void) { window_set_window_handlers(window, (WindowHandlers) { .load = window_load, .unload = window_unload, + .appear = window_appear, }); } @@ -69,7 +73,7 @@ static int16_t menu_get_cell_height_callback(struct MenuLayer *menu_layer, MenuI if (headlines_get_error()) { return graphics_text_layout_get_content_size(headlines_get_error(), fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), bounds, GTextOverflowModeFill, GTextAlignmentLeft).h + 12; } - return graphics_text_layout_get_content_size(headlines_get(cell_index->row)->title, fonts_get_system_font(settings()->headlines_font_size ? FONT_KEY_GOTHIC_24 : FONT_KEY_GOTHIC_18), bounds, GTextOverflowModeFill, GTextAlignmentLeft).h + (settings()->headlines_font_size ? 10 : 8); + return graphics_text_layout_get_content_size(headlines_get(cell_index->row)->title, settings_get_headlines_font_size(), bounds, GTextOverflowModeFill, GTextAlignmentLeft).h + (settings()->headlines_font_size ? 10 : 8); } static void menu_draw_header_callback(GContext *ctx, const Layer *cell_layer, uint16_t section_index, void *callback_context) { @@ -78,12 +82,13 @@ static void menu_draw_header_callback(GContext *ctx, const Layer *cell_layer, ui static void menu_draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *callback_context) { GRect bounds = layer_get_bounds(menu_layer_get_layer(menu_layer)); + //bounds.origin.y -= s_title_bar_height; GRECT_EDGE_TRIM (bounds, TEXT_BORDER_INSET) - graphics_context_set_text_color(ctx, GColorBlack); + graphics_context_set_text_color(ctx, (menu_cell_layer_is_highlighted(cell_layer) ? settings_get_colors()->inverted_text : settings_get_colors()->main_text)); if (headlines_get_error()) { graphics_draw_text(ctx, headlines_get_error(), fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), bounds, GTextOverflowModeFill, PBL_IF_ROUND_ELSE(GTextAlignmentCenter, GTextAlignmentLeft), NULL); } else { - graphics_draw_text(ctx, headlines_get(cell_index->row)->title, fonts_get_system_font(settings()->headlines_font_size ? FONT_KEY_GOTHIC_24 : FONT_KEY_GOTHIC_18), bounds, GTextOverflowModeFill, PBL_IF_ROUND_ELSE(GTextAlignmentCenter, GTextAlignmentLeft), NULL); + graphics_draw_text(ctx, headlines_get(cell_index->row)->title, settings_get_headlines_font_size(), bounds, GTextOverflowModeFill, PBL_IF_ROUND_ELSE(GTextAlignmentCenter, GTextAlignmentLeft), NULL); } } @@ -99,10 +104,11 @@ static void menu_select_long_callback(struct MenuLayer *menu_layer, MenuIndex *c rss_add_to_pocket(); } -static void window_load(Window *window) { - //Layer *window_layer = window_get_root_layer(window); - //GRect bounds = layer_get_bounds(window_layer); +static void window_appear(Window *window) { + window_set_colors(window); +} +static void window_load(Window *window) { menu_layer = menu_layer_create_fullscreen(window); menu_layer_set_callbacks(menu_layer, NULL, (MenuLayerCallbacks) { .get_num_rows = menu_get_num_rows_callback, @@ -116,24 +122,21 @@ static void window_load(Window *window) { menu_layer_set_click_config_onto_window(menu_layer, window); menu_layer_add_to_window(menu_layer, window); -#define STATUS_BAR_SIZE_MAX (STATUS_BAR_LAYER_HEIGHT + 12) - -#ifdef PBL_SDK_3 // Set up the status bar if it's needed s_status_bar = title_bar_layer_create_fullscreen(window); - title_bar_layer_set_colors(s_status_bar, GColorBlack, GColorPastelYellow); title_bar_layer_set_text(s_status_bar, subscriptions_get_current()->title); -#endif + s_title_bar_height = title_bar_layer_get_height(s_status_bar); -#ifdef PBL_COLOR - menu_layer_set_normal_colors(menu_layer, GColorWhite, GColorBlack); - menu_layer_set_highlight_colors(menu_layer, GColorOrange, GColorWhite); +#ifdef PBL_RECT + GRect menu_bounds = layer_get_frame(menu_layer_get_layer(menu_layer)); + menu_bounds.origin.y += s_title_bar_height; + menu_bounds.size.h -= s_title_bar_height; + scroll_layer_set_frame(menu_layer_get_scroll_layer(menu_layer), menu_bounds); #endif // Set up the progress layer s_progress_bar_layer = progress_bar_layer_create_fullscreen(window); - progress_bar_layer_set_pos(s_progress_bar_layer, TITLE_BAR_DEFAULT_HEIGHT); - progress_bar_layer_set_colors(s_progress_bar_layer, GColorOrange, GColorWhite); + progress_bar_layer_set_pos(s_progress_bar_layer, s_title_bar_height); } static void window_unload(Window *window) { @@ -148,3 +151,10 @@ static void window_unload(Window *window) { progress_bar_layer_destroy(s_progress_bar_layer); } +static void window_set_colors(Window * window) { + title_bar_layer_set_colors(s_status_bar, settings_get_colors()->title_bar_text, settings_get_colors()->title_bar_background); + menu_layer_set_normal_colors(menu_layer, settings_get_colors()->main_background, settings_get_colors()->main_text); + menu_layer_set_highlight_colors(menu_layer, settings_get_colors()->selection_highlight, settings_get_colors()->inverted_text); + progress_bar_layer_set_colors(s_progress_bar_layer, settings_get_colors()->progress_bar_complete, settings_get_colors()->progress_bar_remaining); +} + diff --git a/src/windows/win-settings.c b/src/windows/win-settings.c index c3fd75a..f3d1be4 100644 --- a/src/windows/win-settings.c +++ b/src/windows/win-settings.c @@ -24,6 +24,8 @@ static void menu_draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuI static void menu_select_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context); static void window_load(Window *window); static void window_unload(Window *window); +static void window_set_colors(Window * window); +static void window_appear(Window *window); static Window *window = NULL; static MenuLayer *menu_layer = NULL; @@ -43,6 +45,7 @@ void win_settings_init(void) { window_set_window_handlers(window, (WindowHandlers) { .load = window_load, .unload = window_unload, + .appear = window_appear, }); } @@ -86,16 +89,16 @@ static void menu_draw_header_callback(GContext *ctx, const Layer *cell_layer, ui } static void menu_draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *callback_context) { - char value[6] = ""; + char const *value = NULL; switch (cell_index->row) { case MENU_ROW_HEADLINES_SIZE: - strncpy(value, settings()->headlines_font_size ? "Large": "Small", sizeof(value)); + value = settings_get_headlines_font_size_string(); break; case MENU_ROW_SUMMARY_SIZE: - strncpy(value, settings()->story_font_size ? "Large": "Small", sizeof(value)); + value = settings_get_story_font_size_string(); break; case MENU_ROW_SUMMARY_COLOR: - strncpy(value, settings()->story_font_color ? "White": "Black", sizeof(value)); + value = settings_get_story_font_color_string(); break; } menu_cell_basic_draw(ctx, cell_layer, settings_labels[cell_index->row], value, NULL); @@ -104,18 +107,23 @@ static void menu_draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuI static void menu_select_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context) { switch (cell_index->row) { case MENU_ROW_HEADLINES_SIZE: - settings()->headlines_font_size = !settings()->headlines_font_size; + settings_bump_headlines_font_size(); break; case MENU_ROW_SUMMARY_SIZE: - settings()->story_font_size = !settings()->story_font_size; + settings_bump_story_font_size(); break; case MENU_ROW_SUMMARY_COLOR: - settings()->story_font_color = !settings()->story_font_color; + settings_bump_story_font_color(); + window_set_colors(window); break; } menu_layer_reload_data(menu_layer); } +static void window_appear(Window *window) { + window_set_colors(window); +} + static void window_load(Window *window) { Layer *window_layer = window_get_root_layer(window); #ifdef PBL_ROUND @@ -138,26 +146,19 @@ static void window_load(Window *window) { // Set up the status bar if it's needed s_status_bar = status_bar_layer_create(); layer_add_child(window_layer, status_bar_layer_get_layer(s_status_bar)); - status_bar_layer_set_colors(s_status_bar, GColorWhite, GColorBlack); #ifdef PBL_ROUND // Set up the lower message bar const GEdgeInsets message_insets = {.top = bounds.size.h - STATUS_BAR_LAYER_HEIGHT}; s_lower_bar = text_layer_create(grect_inset(bounds, message_insets)); text_layer_set_text_alignment(s_lower_bar, GTextAlignmentCenter); - text_layer_set_colors(s_lower_bar, GColorBlack, GColorWhite); text_layer_set_text(s_lower_bar, ""); layer_add_child(window_layer, text_layer_get_layer(s_lower_bar)); #else - GRect menu_bounds = layer_get_bounds(menu_layer_get_layer(menu_layer)); + GRect menu_bounds = layer_get_frame(menu_layer_get_layer(menu_layer)); menu_bounds.origin.y += STATUS_BAR_LAYER_HEIGHT; - menu_bounds.size.h -= STATUS_BAR_LAYER_HEIGHT * 2; - layer_set_bounds(menu_layer_get_layer(menu_layer), menu_bounds); -#endif - -#ifdef PBL_COLOR - menu_layer_set_normal_colors(menu_layer, GColorWhite, GColorBlack); - menu_layer_set_highlight_colors(menu_layer, GColorOrange, GColorWhite); + menu_bounds.size.h -= STATUS_BAR_LAYER_HEIGHT; + scroll_layer_set_frame(menu_layer_get_scroll_layer(menu_layer), menu_bounds); #endif } @@ -171,3 +172,12 @@ static void window_unload(Window *window) { #endif } +static void window_set_colors(Window * window) { + status_bar_layer_set_colors(s_status_bar, settings_get_colors()->main_background, settings_get_colors()->main_text); + menu_layer_set_normal_colors(menu_layer, settings_get_colors()->main_background, settings_get_colors()->main_text); + menu_layer_set_highlight_colors(menu_layer, settings_get_colors()->selection_highlight, settings_get_colors()->inverted_text); +#ifdef PBL_ROUND + text_layer_set_colors(s_lower_bar, settings_get_colors()->main_text, settings_get_colors()->main_background); +#endif +} + diff --git a/src/windows/win-story.c b/src/windows/win-story.c index 94035ce..226bc88 100644 --- a/src/windows/win-story.c +++ b/src/windows/win-story.c @@ -21,12 +21,15 @@ static ScrollLayer *scroll_layer = NULL; static TextLayer *title_text_layer = NULL; static TextLayer *story_text_layer = NULL; static ProgressBarLayer *progress_bar_layer = NULL; +static void window_set_colors(Window * window); +static void window_appear(Window *window); void win_story_init(void) { window = window_create(); window_set_window_handlers(window, (WindowHandlers) { .load = window_load, .unload = window_unload, + .appear = window_appear, }); } @@ -79,21 +82,25 @@ static void click_config_provider(void *context) { window_long_click_subscribe(BUTTON_ID_SELECT, 500, select_long_click_handler, NULL); } +static void window_appear(Window *window) { + window_set_colors(window); +} + static void window_load(Window *window) { //window_set_background_color(window, settings()->story_font_color ? GColorBlack : GColorWhite); - window_set_background_color(window, GColorWhite); + //window_set_background_color(window, GColorWhite); GRect window_bounds = layer_get_bounds(window_get_root_layer(window)); story_text_layer = text_layer_create(window_bounds); - text_layer_set_colors(story_text_layer, GColorBlack, GColorWhite); - text_layer_set_font(story_text_layer, fonts_get_system_font(settings()->story_font_size ? FONT_KEY_GOTHIC_24 : FONT_KEY_GOTHIC_14)); + //text_layer_set_colors(story_text_layer, GColorBlack, GColorWhite); + text_layer_set_font(story_text_layer, settings_get_story_body_font_size()); text_layer_set_text_alignment(story_text_layer, GTextAlignmentCenter); text_layer_set_text(story_text_layer, "Loading..."); title_text_layer = text_layer_create(window_bounds); - text_layer_set_colors(title_text_layer, GColorBlack, GColorPastelYellow); - text_layer_set_font(title_text_layer, fonts_get_system_font(settings()->story_font_size ? FONT_KEY_GOTHIC_24_BOLD : FONT_KEY_GOTHIC_14_BOLD)); + //text_layer_set_colors(title_text_layer, GColorBlack, GColorPastelYellow); + text_layer_set_font(title_text_layer, settings_get_story_title_font_size()); text_layer_set_text_alignment(title_text_layer, GTextAlignmentCenter); text_layer_set_text(title_text_layer, headlines_get_current()->title); @@ -168,7 +175,7 @@ static void window_load(Window *window) { // Set up the progress layer progress_bar_layer = progress_bar_layer_create_fullscreen(window); progress_bar_layer_set_pos(progress_bar_layer, title_layer_size.h); - progress_bar_layer_set_colors(progress_bar_layer, GColorOrange, GColorWhite); + //progress_bar_layer_set_colors(progress_bar_layer, GColorOrange, GColorWhite); progress_bar_layer_set_progress(progress_bar_layer, 0); scroll_layer_add_child(scroll_layer, progress_bar_layer_get_layer(progress_bar_layer)); } @@ -182,3 +189,10 @@ static void window_unload(Window *window) { progress_bar_layer_destroy(progress_bar_layer); } +static void window_set_colors(Window * window) { + window_set_background_color(window, settings_get_colors()->main_background); + text_layer_set_colors(story_text_layer, settings_get_colors()->main_text, settings_get_colors()->main_background); + text_layer_set_colors(title_text_layer, settings_get_colors()->title_bar_text, settings_get_colors()->title_bar_background); + progress_bar_layer_set_colors(progress_bar_layer, settings_get_colors()->progress_bar_complete, settings_get_colors()->progress_bar_remaining); +} + diff --git a/src/windows/win-subscriptions.c b/src/windows/win-subscriptions.c index 1a48208..3817fef 100644 --- a/src/windows/win-subscriptions.c +++ b/src/windows/win-subscriptions.c @@ -5,6 +5,7 @@ #include "rss.h" #include "win-headlines.h" #include "win-settings.h" +#include "settings.h" #define MENU_NUM_SECTIONS (1) #define TEXT_BORDER_INSET (16) @@ -23,6 +24,8 @@ static void window_load(Window *window); static void window_unload(Window *window); int menu_item_count(); int menu_item_settings_pos(); +static void window_set_colors(Window * window); +static void window_appear(Window *window); static Window *window = NULL; static MenuLayer *menu_layer = NULL; @@ -54,6 +57,7 @@ void win_subscriptions_init(void) { window_set_window_handlers(window, (WindowHandlers) { .load = window_load, .unload = window_unload, + .appear = window_appear, }); window_stack_push(window, true); } @@ -67,6 +71,9 @@ void win_subscriptions_reload_data_and_mark_dirty(void) { menu_layer_reload_data_and_mark_dirty(menu_layer); } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // static uint16_t menu_get_num_sections_callback(struct MenuLayer *menu_layer, void *callback_context) { @@ -98,13 +105,15 @@ static void menu_draw_header_callback(GContext *ctx, const Layer *cell_layer, ui static void menu_draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *callback_context) { if (cell_index->row == menu_item_settings_pos()) { #ifdef PBL_COLOR - graphics_context_set_text_color(ctx, GColorBlue); + graphics_context_set_text_color(ctx, (menu_cell_layer_is_highlighted(cell_layer) ? settings_get_colors()->settings_inverted_text : settings_get_colors()->settings_text)); #endif menu_cell_basic_draw(ctx, cell_layer, "Settings", NULL, NULL); } else if (subscriptions_get_error()) { - //graphics_context_set_text_color(ctx, GColorBlack); GRect bounds = layer_get_bounds(cell_layer); GRECT_EDGE_TRIM (bounds, TEXT_BORDER_INSET) + + graphics_context_set_text_color(ctx, (menu_cell_layer_is_highlighted(cell_layer) ? settings_get_colors()->inverted_text : settings_get_colors()->main_text)); + graphics_draw_text(ctx, subscriptions_get_error(), fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), bounds, GTextOverflowModeFill, PBL_IF_ROUND_ELSE (GTextAlignmentCenter, GTextAlignmentLeft), NULL); } else { menu_cell_basic_draw(ctx, cell_layer, subscriptions_get(cell_index->row)->title, NULL, NULL); @@ -124,6 +133,10 @@ static void menu_select_long_callback(struct MenuLayer *menu_layer, MenuIndex *c rss_request_subscriptions(); } +static void window_appear(Window *window) { + window_set_colors(window); +} + static void window_load(Window *window) { Layer *window_layer = window_get_root_layer(window); #ifdef PBL_ROUND @@ -135,8 +148,8 @@ static void window_load(Window *window) { .get_num_sections = menu_get_num_sections_callback, .get_num_rows = menu_get_num_rows_callback, .get_header_height = menu_get_header_height_callback, - .get_cell_height = menu_get_cell_height_callback, .draw_header = menu_draw_header_callback, + .get_cell_height = menu_get_cell_height_callback, .draw_row = menu_draw_row_callback, .select_click = menu_select_callback, .select_long_click = menu_select_long_callback, @@ -147,26 +160,19 @@ static void window_load(Window *window) { // Set up the status bar if it's needed s_status_bar = status_bar_layer_create(); layer_add_child(window_layer, status_bar_layer_get_layer(s_status_bar)); - status_bar_layer_set_colors(s_status_bar, GColorWhite, GColorBlack); #ifdef PBL_ROUND // Set up the lower message bar const GEdgeInsets message_insets = {.top = bounds.size.h - STATUS_BAR_LAYER_HEIGHT}; s_lower_bar = text_layer_create(grect_inset(bounds, message_insets)); text_layer_set_text_alignment(s_lower_bar, GTextAlignmentCenter); - text_layer_set_colors(s_lower_bar, GColorBlack, GColorWhite); text_layer_set_text(s_lower_bar, ""); layer_add_child(window_layer, text_layer_get_layer(s_lower_bar)); #else - GRect menu_bounds = layer_get_bounds(menu_layer_get_layer(menu_layer)); + GRect menu_bounds = layer_get_frame(menu_layer_get_layer(menu_layer)); menu_bounds.origin.y += STATUS_BAR_LAYER_HEIGHT; - menu_bounds.size.h -= STATUS_BAR_LAYER_HEIGHT * 2; - layer_set_bounds(menu_layer_get_layer(menu_layer), menu_bounds); -#endif - -#ifdef PBL_COLOR - menu_layer_set_normal_colors(menu_layer, GColorWhite, GColorBlack); - menu_layer_set_highlight_colors(menu_layer, GColorOrange, GColorWhite); + menu_bounds.size.h -= STATUS_BAR_LAYER_HEIGHT; + scroll_layer_set_frame(menu_layer_get_scroll_layer(menu_layer), menu_bounds); #endif } @@ -180,4 +186,12 @@ static void window_unload(Window *window) { #endif } +static void window_set_colors(Window * window) { + status_bar_layer_set_colors(s_status_bar, settings_get_colors()->main_background, settings_get_colors()->main_text); + menu_layer_set_normal_colors(menu_layer, settings_get_colors()->main_background, settings_get_colors()->main_text); + menu_layer_set_highlight_colors(menu_layer, settings_get_colors()->selection_highlight, settings_get_colors()->inverted_text); +#ifdef PBL_ROUND + text_layer_set_colors(s_lower_bar, settings_get_colors()->main_text, settings_get_colors()->main_background); +#endif +} From e44ee2ff5ac39d62c9371b37f65b2cc8eebfffc2 Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Thu, 14 Jan 2016 21:40:16 +0000 Subject: [PATCH 09/13] Reduce inbox and outbox size The buffer sizes cause problems for aplite watches due to lack of memory. The code set them to app_message_inbox_size_maximum and app_message_outbox_size_maximum which was 8k for SDK 4.0. This size also seemed unecessary, so this reduces both to 440B. This should be enough for the largest headline (160B) and the largest feed name (30B) as set in main.js. Also fix the wscript which was copying all of the javascript files into the .pbw file, whereas it should only be pebble-js-app.js --- src/js/src/appmessagequeue.js | 3 +-- src/rss.c | 7 +++++-- wscript | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/js/src/appmessagequeue.js b/src/js/src/appmessagequeue.js index d985c4a..700cbaf 100644 --- a/src/js/src/appmessagequeue.js +++ b/src/js/src/appmessagequeue.js @@ -24,8 +24,7 @@ var appMessageQueue = { appMessageQueue.working = false; appMessageQueue.send(); }; - var nack = function(data) { - console.log("Error: " + JSON.stringify(data)); + var nack = function() { appMessageQueue.numTries++; appMessageQueue.working = false; appMessageQueue.send(); diff --git a/src/rss.c b/src/rss.c index 207490e..fcc9a78 100644 --- a/src/rss.c +++ b/src/rss.c @@ -8,6 +8,9 @@ #include "headlines.h" #include "story.h" +#define INBOX_SIZE_MAX (440) +#define OUTBOX_SIZE_MAX (440) + static void in_received_handler(DictionaryIterator *iter, void *context); static void out_failed_handler(DictionaryIterator *failed, AppMessageResult reason, void *context); static void timer_callback(void *data); @@ -18,7 +21,7 @@ static char *error = NULL; void rss_init(void) { app_message_register_inbox_received(in_received_handler); app_message_register_outbox_failed(out_failed_handler); - app_message_open_max(); + app_message_open(INBOX_SIZE_MAX, OUTBOX_SIZE_MAX); timer = app_timer_register(1000, timer_callback, NULL); @@ -103,7 +106,7 @@ static void timer_callback(void *data) { dict_write_uint8(iter, APP_KEY_METHOD, KEY_METHOD_BUFFERSIZE); //dict_write_uint32(iter, APP_KEY_INDEX, app_message_inbox_size_maximum()); // Reducing the size of the buffer allows the story to be sent in chunks - uint32_t buffersize = 128; + uint32_t buffersize = INBOX_SIZE_MAX; if (buffersize > app_message_inbox_size_maximum()) { buffersize = app_message_inbox_size_maximum(); } diff --git a/wscript b/wscript index f258540..86b0aee 100644 --- a/wscript +++ b/wscript @@ -73,7 +73,7 @@ def build(ctx): # Bundle everything needed into the pbw file ctx.set_group('bundle') - ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob('src/js/**/*.js')) + ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob('src/js/pebble-js-app.js')) def generate_appinfo_h(task): src = task.inputs[0].abspath() From 64d3f57f0a765146692cbb0b480a8f61661607aa Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Fri, 15 Jan 2016 21:33:19 +0000 Subject: [PATCH 10/13] Tweak colours to improve dark theme Increase the yellow of the selection bar, otherwise it just looks like white. --- src/settings.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/settings.c b/src/settings.c index e129d17..e8839d3 100644 --- a/src/settings.c +++ b/src/settings.c @@ -45,10 +45,10 @@ static const InterfaceColors s_interface_colors[] = { .main_background = {GColorBlackARGB8}, .main_text = {GColorWhiteARGB8}, .inverted_text = {GColorBlackARGB8}, - .selection_highlight = {GColorPastelYellowARGB8}, + .selection_highlight = {GColorIcterineARGB8}, .title_bar_background = {GColorOrangeARGB8}, .title_bar_text = {GColorWhiteARGB8}, - .progress_bar_complete = {GColorPastelYellowARGB8}, + .progress_bar_complete = {GColorIcterineARGB8}, .progress_bar_remaining = {GColorBlackARGB8}, .settings_text = {GColorCelesteARGB8}, .settings_inverted_text = {GColorBlueARGB8} From a02647ddcc4c40617fbbbf9d09eca17a604fc1bb Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Sun, 17 Jan 2016 00:11:30 +0000 Subject: [PATCH 11/13] Squash height of title bar to text Reduce the height of the title bar text (used on the headlines page) to the height of the text contained within it. This leaves more space for the main content (the headlines menu list). --- src/layers/title_bar.c | 17 +++++++++++++++-- src/layers/title_bar.h | 1 + src/subscriptions.c | 2 +- src/windows/win-headlines.c | 9 +++------ src/windows/win-story.c | 31 ------------------------------- 5 files changed, 20 insertions(+), 40 deletions(-) diff --git a/src/layers/title_bar.c b/src/layers/title_bar.c index 8c1e197..f308820 100644 --- a/src/layers/title_bar.c +++ b/src/layers/title_bar.c @@ -1,7 +1,11 @@ #include #include "layers/title_bar.h" +#include "libs/pebble-assist.h" -typedef struct TitleBarData { +#define TITLE_LAYER_PAD (8) +#define TITLE_TEXT_PAD (4) + +typedef struct _TitleBarData { TitleBarLayerUpdateProc update_proc; GColor foreground; GColor background; @@ -43,6 +47,7 @@ TitleBarLayer * title_bar_layer_create(GRect bounds) { text_layer_set_text_alignment(title_bar_data->text_layer, GTextAlignmentCenter); text_layer_set_text_color(title_bar_data->text_layer, GColorBlack); text_layer_set_background_color(title_bar_data->text_layer, GColorClear); + text_layer_set_font(title_bar_data->text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD)); layer_add_child((Layer*)title_bar_layer, text_layer_get_layer(title_bar_data->text_layer)); @@ -105,6 +110,14 @@ int16_t title_bar_layer_get_height(TitleBarLayer * title_bar_layer) { return layer_bounds.size.h; } +void title_bar_layer_reduce_height(TitleBarLayer * title_bar_layer) { + TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); + + GSize title_layer_size = text_layer_get_content_size(title_bar_data->text_layer); + int16_t height = title_layer_size.h + TITLE_LAYER_PAD; + title_bar_layer_set_height(title_bar_layer, height); +} + void title_bar_layer_set_colors(TitleBarLayer * title_bar_layer, GColor foreground, GColor background) { TitleBarData *title_bar_data = (TitleBarData *)layer_get_data((Layer *)title_bar_layer); @@ -159,7 +172,7 @@ void title_bar_layer_centre_text_vertically(TitleBarLayer * title_bar_layer) { GRect text_bounds = layer_get_bounds(text_layer_get_layer(title_bar_data->text_layer)); GSize text_size = text_layer_get_content_size(title_bar_data->text_layer); - text_bounds.origin.y = (title_bar_bounds.size.h - text_size.h) / 2; + text_bounds.origin.y = (title_bar_bounds.size.h - text_size.h - TITLE_TEXT_PAD) / 2; layer_set_frame(text_layer_get_layer(title_bar_data->text_layer), text_bounds); } diff --git a/src/layers/title_bar.h b/src/layers/title_bar.h index 0a231ce..8e8e844 100644 --- a/src/layers/title_bar.h +++ b/src/layers/title_bar.h @@ -14,6 +14,7 @@ TitleBarLayer * title_bar_layer_create(GRect bounds); void title_bar_layer_destroy(TitleBarLayer * title_bar_layer); void title_bar_layer_set_height(TitleBarLayer * title_bar_layer, int16_t height); int16_t title_bar_layer_get_height(TitleBarLayer * title_bar_layer); +void title_bar_layer_reduce_height(TitleBarLayer * title_bar_layer); void title_bar_layer_set_colors(TitleBarLayer * title_bar_layer, GColor foreground, GColor background); GColor title_bar_layer_get_foreground_color(TitleBarLayer * title_bar_layer); GColor title_bar_layer_get_background_color(TitleBarLayer * title_bar_layer); diff --git a/src/subscriptions.c b/src/subscriptions.c index ecdc2e7..b2b8217 100644 --- a/src/subscriptions.c +++ b/src/subscriptions.c @@ -54,7 +54,7 @@ void subscriptions_in_received_handler(DictionaryIterator *iter) { if (tuple) { strncpy(subscription->title, tuple->value->cstring, sizeof(subscription->title) - 1); } - LOG("subscription: %d '%s'", subscription->index, subscription->title); + //LOG("subscription: %d '%s'", subscription->index, subscription->title); subscriptions_reload_data_and_mark_dirty(); break; } diff --git a/src/windows/win-headlines.c b/src/windows/win-headlines.c index 597274f..5be3339 100644 --- a/src/windows/win-headlines.c +++ b/src/windows/win-headlines.c @@ -29,9 +29,7 @@ static Window *window = NULL; static MenuLayer *menu_layer = NULL; static ProgressBarLayer *s_progress_bar_layer; static int16_t s_title_bar_height; -#ifdef PBL_SDK_3 static TitleBarLayer *s_status_bar; -#endif void win_headlines_init(void) { window = window_create(); @@ -125,6 +123,9 @@ static void window_load(Window *window) { // Set up the status bar if it's needed s_status_bar = title_bar_layer_create_fullscreen(window); title_bar_layer_set_text(s_status_bar, subscriptions_get_current()->title); + + title_bar_layer_reduce_height(s_status_bar); + s_title_bar_height = title_bar_layer_get_height(s_status_bar); #ifdef PBL_RECT @@ -141,12 +142,8 @@ static void window_load(Window *window) { static void window_unload(Window *window) { menu_layer_destroy_safe(menu_layer); - -#ifdef PBL_SDK_3 // Destroy the status bar if there is one title_bar_layer_destroy(s_status_bar); -#endif - // Destroy the progress bar progress_bar_layer_destroy(s_progress_bar_layer); } diff --git a/src/windows/win-story.c b/src/windows/win-story.c index 226bc88..471106f 100644 --- a/src/windows/win-story.c +++ b/src/windows/win-story.c @@ -87,19 +87,15 @@ static void window_appear(Window *window) { } static void window_load(Window *window) { - //window_set_background_color(window, settings()->story_font_color ? GColorBlack : GColorWhite); - //window_set_background_color(window, GColorWhite); GRect window_bounds = layer_get_bounds(window_get_root_layer(window)); story_text_layer = text_layer_create(window_bounds); - //text_layer_set_colors(story_text_layer, GColorBlack, GColorWhite); text_layer_set_font(story_text_layer, settings_get_story_body_font_size()); text_layer_set_text_alignment(story_text_layer, GTextAlignmentCenter); text_layer_set_text(story_text_layer, "Loading..."); title_text_layer = text_layer_create(window_bounds); - //text_layer_set_colors(title_text_layer, GColorBlack, GColorPastelYellow); text_layer_set_font(title_text_layer, settings_get_story_title_font_size()); text_layer_set_text_alignment(title_text_layer, GTextAlignmentCenter); text_layer_set_text(title_text_layer, headlines_get_current()->title); @@ -146,36 +142,9 @@ static void window_load(Window *window) { scroll_layer_set_paging(scroll_layer, true); - - - //text_layer_set_colors(title_text_layer, settings()->story_font_color ? GColorWhite : GColorBlack, GColorPastelYellow); - //text_layer_set_font(title_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD)); - //text_layer_set_text(title_text_layer, headlines_get_current()->title); - - //scroll_layer_add_child(scroll_layer, text_layer_get_layer(title_text_layer)); - //text_layer_enable_screen_text_flow_and_paging(title_text_layer, 2); - - //GSize title_layer_size = text_layer_get_content_size(title_text_layer); - //title_layer_size.w = window_bounds.size.w; - //title_layer_size.h += 8; - - //text_layer_set_size(title_text_layer, title_layer_size); - - //GRect text_layer_bounds = window_bounds; - //text_layer_bounds.origin.y = title_layer_size.h; - //story_text_layer = text_layer_create(text_layer_bounds); - //text_layer_set_colors(story_text_layer, settings()->story_font_color ? GColorWhite : GColorBlack, GColorClear); - - - //GSize story_layer_size = text_layer_get_content_size(story_text_layer); - //story_layer_size.h = story_layer_size.h + 8; - //story_layer_size.h = window_bounds.size.h; - //text_layer_set_size(story_text_layer, story_layer_size); - // Set up the progress layer progress_bar_layer = progress_bar_layer_create_fullscreen(window); progress_bar_layer_set_pos(progress_bar_layer, title_layer_size.h); - //progress_bar_layer_set_colors(progress_bar_layer, GColorOrange, GColorWhite); progress_bar_layer_set_progress(progress_bar_layer, 0); scroll_layer_add_child(scroll_layer, progress_bar_layer_get_layer(progress_bar_layer)); } From b2be38b760345370fa0ab8f79e844c6aca55ac18 Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Mon, 21 Mar 2016 10:24:46 +0000 Subject: [PATCH 12/13] Fix wscript (thanks to @ogerardin) to avoid needing two build runs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An error in the wscript file meant the generated Javascript file wasn't being included in the final pbw file. This change fixes this, with thanks to Olivier GĂ©rardin (https://github.com/ogerardin) for highlighting the problem and identifying the fix. --- wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wscript b/wscript index 86b0aee..44778f2 100644 --- a/wscript +++ b/wscript @@ -73,7 +73,7 @@ def build(ctx): # Bundle everything needed into the pbw file ctx.set_group('bundle') - ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob('src/js/pebble-js-app.js')) + ctx.pbl_bundle(binaries=binaries, js='../src/js/pebble-js-app.js') def generate_appinfo_h(task): src = task.inputs[0].abspath() From bd7dd4903c0aa4f078a6989d5ae66e2bb9f20c7d Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Mon, 21 Mar 2016 10:38:51 +0000 Subject: [PATCH 13/13] Added content-type header when adding to Pocket To fix issue #6 preventing Pocket integration from working properly. This adds the fix identified by @ydyu see: https://github.com/Neal/Readebble/issues/6#issuecomment-198852569 --- src/js/src/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/src/main.js b/src/js/src/main.js index 205928e..b1b00a6 100644 --- a/src/js/src/main.js +++ b/src/js/src/main.js @@ -96,7 +96,7 @@ Readebble.addToPocket = function() { if (!Readebble.pocket.access_token) return Pebble.showSimpleNotificationOnPebble('Readebble', 'No Pocket account found. Please log in to your Pocket account via the Pebble mobile app.'); var url = 'https://ineal.me/pebble/readebble/pocket/add'; var data = { access_token: Readebble.pocket.access_token, url: Readebble.currentHeadline.link }; - http('POST', url, serialize(data), null, function (e) { + http('POST', url, serialize(data), {"Content-Type": "application/x-www-form-urlencoded"}, function (e) { var res = JSON.parse(e.responseText); debugLog(res); if (res.item && res.status == 1) {