Works on all three platforms

master
Neale Pickett 2015-12-25 13:32:26 -07:00
parent 01033395eb
commit a84417f1a7
13 changed files with 441 additions and 0 deletions

121
appinfo.json 100644
View File

@ -0,0 +1,121 @@
{
"appKeys": {
"align": 1,
"font": 2,
"theme": 0
},
"capabilities": [
""
],
"companyName": "dartcatcher@gmail.com",
"longName": "Twatch Fonts",
"projectType": "native",
"resources": {
"media": [
{
"characterRegex": "[\uf10b]",
"file": "fonts/fontawesome.ttf",
"name": "FONT_SYMBOLS_52",
"targetPlatforms": null,
"type": "font"
},
{
"characterRegex": "[0-9:]",
"file": "fonts/Ubuntu-Bold.ttf",
"name": "FONT_UBUNTU_B_64",
"targetPlatforms": [
"chalk"
],
"type": "font"
},
{
"characterRegex": "[0-9:]",
"file": "fonts/Ubuntu-Bold.ttf",
"name": "FONT_UBUNTU_B_48",
"targetPlatforms": [
"aplite",
"basalt"
],
"type": "font"
},
{
"characterRegex": "[0-9A-Za-z\u00e9\u00f4 ]",
"file": "fonts/Ubuntu-Regular.ttf",
"name": "FONT_UBUNTU_R_28",
"targetPlatforms": null,
"type": "font"
},
{
"characterRegex": "[0-9A-Za-z\u00e9\u00f4 ]",
"file": "fonts/AveriaSerif-Regular.ttf",
"name": "FONT_AVERIA_R_28",
"targetPlatforms": null,
"type": "font"
},
{
"characterRegex": "[0-9:]",
"file": "fonts/AveriaSerif-Bold.ttf",
"name": "FONT_AVERIA_B_64",
"targetPlatforms": [
"chalk"
],
"type": "font"
},
{
"characterRegex": "[0-9:]",
"file": "fonts/AveriaSerif-Bold.ttf",
"name": "FONT_AVERIA_B_48",
"targetPlatforms": [
"aplite",
"basalt"
],
"type": "font"
},
{
"file": "images/icon.png",
"menuIcon": true,
"name": "ICON",
"targetPlatforms": null,
"type": "bitmap"
},
{
"characterRegex": "[0-9A-Za-z\u00e9\u00f4 ]",
"file": "fonts/Helvetica-Regular.ttf",
"name": "FONT_HELVETICA_R_28",
"targetPlatforms": null,
"type": "font"
},
{
"characterRegex": "[0-9:]",
"file": "fonts/Helvetica-Bold.ttf",
"name": "FONT_HELVETICA_B_64",
"targetPlatforms": [
"chalk"
],
"type": "font"
},
{
"characterRegex": "[0-9:]",
"file": "fonts/Helvetica-Bold.ttf",
"name": "FONT_HELVETICA_B_48",
"targetPlatforms": [
"aplite",
"basalt"
],
"type": "font"
}
]
},
"sdkVersion": "3",
"shortName": "Twatch Fonts",
"targetPlatforms": [
"aplite",
"basalt",
"chalk"
],
"uuid": "2dce4324-374b-4e5e-9b98-3275561118f3",
"versionLabel": "1.0",
"watchapp": {
"watchface": true
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 B

162
src/main.c 100644
View File

@ -0,0 +1,162 @@
#include <pebble.h>
#include "settings.h"
static Window *s_main_window;
static TextLayer *s_date_layer, *s_time_layer, *s_alert_layer;
bool bt_connected = false;
static void bt_handler(bool connected) {
bt_connected = connected;
if (! bt_connected) {
vibes_double_pulse();
}
layer_mark_dirty(text_layer_get_layer(s_alert_layer));
}
static void handle_minute_tick(struct tm *tick_time, TimeUnits units_changed) {
// Need to be static because they're used by the system later.
static char s_time_text[] = "00:00";
static char s_date_text[] = "00 Çêû";
// Bluetooth alert
if (bt_connected) {
text_layer_set_text(s_alert_layer, "");
} else {
text_layer_set_text(s_alert_layer, "");
}
// Date
strftime(s_date_text, sizeof(s_date_text), "%d %b", tick_time);
text_layer_set_text(s_date_layer, NOZERO(s_date_text));
// Time
if (clock_is_24h_style()) {
strftime(s_time_text, sizeof(s_time_text), "%R", tick_time);
} else {
strftime(s_time_text, sizeof(s_time_text), "%I:%M", tick_time);
}
text_layer_set_text(s_time_layer, NOZERO(s_time_text));
}
static void main_window_load(Window *window) {
Layer *window_layer = window_get_root_layer(window);
#ifdef PBL_RECT
s_date_layer = text_layer_create(GRect(8, 66, 128, 100));
s_time_layer = text_layer_create(GRect(7, 92, 130, 76));
s_alert_layer = text_layer_create(GRect(110, 7, 52, 52));
text_layer_set_text_alignment(s_date_layer, GTextAlignmentLeft);
text_layer_set_text_alignment(s_time_layer, GTextAlignmentLeft);
#else
s_date_layer = text_layer_create(GRect(0, 20, 180, 100));
s_time_layer = text_layer_create(GRect(0, 48, 180, 76));
s_alert_layer = text_layer_create(GRect(0, 120, 180, 52));
text_layer_set_text_alignment(s_date_layer, GTextAlignmentCenter);
text_layer_set_text_alignment(s_time_layer, GTextAlignmentCenter);
text_layer_set_text_alignment(s_alert_layer, GTextAlignmentCenter);
#endif
text_layer_set_background_color(s_date_layer, GColorClear);
layer_add_child(window_layer, text_layer_get_layer(s_date_layer));
text_layer_set_background_color(s_time_layer, GColorClear);
layer_add_child(window_layer, text_layer_get_layer(s_time_layer));
text_layer_set_background_color(s_alert_layer, GColorClear);
text_layer_set_font(s_alert_layer, fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_SYMBOLS_52)));
layer_add_child(window_layer, text_layer_get_layer(s_alert_layer));
}
static void restore() {
int sel_theme = 0;
int sel_font = 0;
int i;
for (i = 0; i < KEY_LAST; i += 1) {
if (! persist_exists(i)) {
continue;
}
switch (i) {
case KEY_THEME:
sel_theme = persist_read_int(i);
break;
case KEY_FONT:
sel_font = persist_read_int(i);
break;
}
}
window_set_background_color(s_main_window, *themes[sel_theme][0]);
text_layer_set_text_color(s_date_layer, *themes[sel_theme][1]);
text_layer_set_text_color(s_time_layer, *themes[sel_theme][2]);
text_layer_set_text_color(s_alert_layer, *themes[sel_theme][2]);
text_layer_set_font(s_date_layer, fonts_load_custom_font(resource_get_handle(fonts[sel_font][0])));
text_layer_set_font(s_time_layer, fonts_load_custom_font(resource_get_handle(fonts[sel_font][1])));
}
static void in_received_handler(DictionaryIterator *rec, void *context) {
int i;
for (i = 0; i < KEY_LAST; i += 1) {
Tuple *cur = dict_find(rec, i);
if (! cur) {
APP_LOG(APP_LOG_LEVEL_DEBUG, "Holy crap! Key %i isn't around!", i);
continue;
}
persist_write_int(i, cur->value->int32);
}
restore();
}
static void in_dropped_handler(AppMessageResult reason, void *context) {
// XXX: I don't understand what we could possibly do here
}
static void main_window_unload(Window *window) {
text_layer_destroy(s_date_layer);
text_layer_destroy(s_time_layer);
text_layer_destroy(s_alert_layer);
}
static void init() {
s_main_window = window_create();
window_set_window_handlers(s_main_window, (WindowHandlers) {
.load = main_window_load,
.unload = main_window_unload,
});
window_stack_push(s_main_window, true);
tick_timer_service_subscribe(MINUTE_UNIT, handle_minute_tick);
bluetooth_connection_service_subscribe(bt_handler);
bt_connected = bluetooth_connection_service_peek();
app_message_register_inbox_received(in_received_handler);
app_message_register_inbox_dropped(in_dropped_handler);
app_message_open(256, 64);
// Prevent starting blank
time_t now = time(NULL);
struct tm *t = localtime(&now);
handle_minute_tick(t, MINUTE_UNIT);
setlocale(LC_ALL, "");
restore();
}
static void deinit() {
window_destroy(s_main_window);
tick_timer_service_unsubscribe();
}
int main() {
init();
app_event_loop();
deinit();
}

View File

@ -0,0 +1,40 @@
var initialized = false;
function appMessageAck(e) {
console.log("Configuration sent");
}
function appMessageNak(e) {
console.log("Configuration not sent: ", e);
}
Pebble.addEventListener("ready", function() {
console.log("ready called!");
initialized = true;
});
Pebble.addEventListener("showConfiguration", function() {
console.log("showing configuration");
Pebble.openURL('http://woozle.org/neale/misc/twatch-config/fonts.html');
});
var themes = {"Dark": 0,
"Light": 1,
"Green": 2};
var aligns = {"Left": 0,
"Center": 1,
"Right": 2};
var fonts = {"Helvetica": 0,
"Avería": 1,
"Ubuntu": 2};
Pebble.addEventListener("webviewclosed", function(e) {
console.log("configuration closed");
// webview closed
var options = JSON.parse(decodeURIComponent(e.response));
options.theme = themes[options.theme];
options.align = aligns[options.align];
options.font = fonts[options.font];
console.log("Options = " + options.theme + options.align + options.font);
Pebble.sendAppMessage(options, appMessageAck, appMessageNak);
});

56
src/settings.h 100644
View File

@ -0,0 +1,56 @@
#include <pebble.h>
#pragma once
#define NOZERO(s) ((*s == '0')?(s+1):s)
typedef enum {
KEY_THEME = 0,
KEY_ALIGN,
KEY_FONT,
KEY_LAST
} MessageKey;
enum {
THEME_DARK = 0,
THEME_LIGHT,
THEME_GREEN,
THEME_LAST
};
enum {
ALIGN_LEFT = 0,
ALIGN_CENTER,
ALIGN_RIGHT,
ALIGN_LAST
};
enum {
FONT_HELVETICA = 0,
FONT_AVERIA,
FONT_UBUNTU,
FONT_LAST
};
GColor8 *themes[THEME_LAST][3] = {
{&GColorBlack, &GColorWhite, &GColorWhite},
{&GColorWhite, &GColorBlack, &GColorBlack},
{&GColorDarkGreen, &GColorWhite, &GColorWhite}
};
GTextAlignment aligns[ALIGN_LAST] = {
GTextAlignmentLeft,
GTextAlignmentCenter,
GTextAlignmentRight
};
const int fonts[FONT_LAST][2] = {
#ifdef PBL_RECT
{RESOURCE_ID_FONT_HELVETICA_R_28, RESOURCE_ID_FONT_HELVETICA_B_48},
{RESOURCE_ID_FONT_AVERIA_R_28, RESOURCE_ID_FONT_AVERIA_B_48},
{RESOURCE_ID_FONT_UBUNTU_R_28, RESOURCE_ID_FONT_UBUNTU_B_48}
#else
{RESOURCE_ID_FONT_HELVETICA_R_28, RESOURCE_ID_FONT_HELVETICA_B_64},
{RESOURCE_ID_FONT_AVERIA_R_28, RESOURCE_ID_FONT_AVERIA_B_64},
{RESOURCE_ID_FONT_UBUNTU_R_28, RESOURCE_ID_FONT_UBUNTU_B_64}
#endif
};

62
wscript 100644
View File

@ -0,0 +1,62 @@
#
# This file is the default set of rules to compile a Pebble project.
#
# Feel free to customize this to your needs.
#
import os.path
try:
from sh import CommandNotFound, jshint, cat, ErrorReturnCode_2
hint = jshint
except (ImportError, CommandNotFound):
hint = None
top = '.'
out = 'build'
def options(ctx):
ctx.load('pebble_sdk')
def configure(ctx):
ctx.load('pebble_sdk')
def build(ctx):
if False and hint is not None:
try:
hint([node.abspath() for node in ctx.path.ant_glob("src/**/*.js")], _tty_out=False) # no tty because there are none in the cloudpebble sandbox.
except ErrorReturnCode_2 as e:
ctx.fatal("\nJavaScript linting failed (you can disable this in Project Settings):\n" + e.stdout)
# Concatenate all our JS files (but not recursively), and only if any JS exists in the first place.
ctx.path.make_node('src/js/').mkdir()
js_paths = ctx.path.ant_glob(['src/*.js', 'src/**/*.js'])
if js_paths:
ctx(rule='cat ${SRC} > ${TGT}', source=js_paths, target='pebble-js-app.js')
has_js = True
else:
has_js = False
ctx.load('pebble_sdk')
build_worker = os.path.exists('worker_src')
binaries = []
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(p)
ctx.pbl_program(source=ctx.path.ant_glob('src/**/*.c'),
target=app_elf)
if build_worker:
worker_elf='{}/pebble-worker.elf'.format(p)
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})
ctx.set_group('bundle')
ctx.pbl_bundle(binaries=binaries, js='pebble-js-app.js' if has_js else [])