feat(layers): information layer
This commit is contained in:
parent
1e600be872
commit
48f336a2eb
12 changed files with 205 additions and 3 deletions
27
package.json
27
package.json
|
|
@ -23,6 +23,9 @@
|
||||||
"messageKeys": [
|
"messageKeys": [
|
||||||
"dummy"
|
"dummy"
|
||||||
],
|
],
|
||||||
|
"capabilities": [
|
||||||
|
"health"
|
||||||
|
],
|
||||||
"resources": {
|
"resources": {
|
||||||
"media": [{
|
"media": [{
|
||||||
"type": "bitmap",
|
"type": "bitmap",
|
||||||
|
|
@ -36,6 +39,30 @@
|
||||||
"file": "character_odd.png",
|
"file": "character_odd.png",
|
||||||
"memoryFormat": "Smallest",
|
"memoryFormat": "Smallest",
|
||||||
"spaceOptimization": "memory"
|
"spaceOptimization": "memory"
|
||||||
|
}, {
|
||||||
|
"type": "bitmap",
|
||||||
|
"name": "ICON_BATTERY_EMPTY",
|
||||||
|
"file": "icon_battery_empty.png",
|
||||||
|
"memoryFormat": "Smallest",
|
||||||
|
"spaceOptimization": "memory"
|
||||||
|
}, {
|
||||||
|
"type": "bitmap",
|
||||||
|
"name": "ICON_BATTERY_HALF",
|
||||||
|
"file": "icon_battery_half.png",
|
||||||
|
"memoryFormat": "Smallest",
|
||||||
|
"spaceOptimization": "memory"
|
||||||
|
}, {
|
||||||
|
"type": "bitmap",
|
||||||
|
"name": "ICON_BATTERY_FULL",
|
||||||
|
"file": "icon_battery_full.png",
|
||||||
|
"memoryFormat": "Smallest",
|
||||||
|
"spaceOptimization": "memory"
|
||||||
|
}, {
|
||||||
|
"type": "bitmap",
|
||||||
|
"name": "ICON_PAWS",
|
||||||
|
"file": "icon_paws.png",
|
||||||
|
"memoryFormat": "Smallest",
|
||||||
|
"spaceOptimization": "memory"
|
||||||
}, {
|
}, {
|
||||||
"type": "font",
|
"type": "font",
|
||||||
"name": "FONT_TORO_36",
|
"name": "FONT_TORO_36",
|
||||||
|
|
|
||||||
BIN
resources/icon_battery_empty.png
Normal file
BIN
resources/icon_battery_empty.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 130 B |
BIN
resources/icon_battery_full.png
Normal file
BIN
resources/icon_battery_full.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 143 B |
BIN
resources/icon_battery_half.png
Normal file
BIN
resources/icon_battery_half.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 143 B |
BIN
resources/icon_paws.png
Normal file
BIN
resources/icon_paws.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 213 B |
|
|
@ -60,6 +60,10 @@ void clock_layer_init(Layer *layer, int y) {
|
||||||
layer_add_child(layer, s_clock_layer);
|
layer_add_child(layer, s_clock_layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GRect clock_layer_get_bounds() {
|
||||||
|
return layer_get_bounds(s_clock_layer);
|
||||||
|
}
|
||||||
|
|
||||||
void clock_layer_tick(void) {
|
void clock_layer_tick(void) {
|
||||||
layer_mark_dirty(s_clock_layer);
|
layer_mark_dirty(s_clock_layer);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@
|
||||||
#include <pebble.h>
|
#include <pebble.h>
|
||||||
|
|
||||||
void clock_layer_init(Layer *layer, int y);
|
void clock_layer_init(Layer *layer, int y);
|
||||||
|
GRect clock_layer_get_bounds();
|
||||||
void clock_layer_tick(void);
|
void clock_layer_tick(void);
|
||||||
void clock_layer_deinit(void);
|
void clock_layer_deinit(void);
|
||||||
|
|
||||||
#endif
|
#endif // CLOCK_LAYER_H_
|
||||||
|
|
|
||||||
115
src/c/information_layer.c
Normal file
115
src/c/information_layer.c
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
#include "information_layer.h"
|
||||||
|
|
||||||
|
#include "resources_service.h"
|
||||||
|
|
||||||
|
#define INFO_LAYER_ICON_WIDTH 18
|
||||||
|
#define INFO_LAYER_PADDING 4
|
||||||
|
#define INFO_LAYER_HEIGHT 24
|
||||||
|
|
||||||
|
typedef struct InformationLayerData {
|
||||||
|
int level;
|
||||||
|
int steps;
|
||||||
|
} InformationLayerData;
|
||||||
|
|
||||||
|
static Layer *s_information_layer;
|
||||||
|
static char s_information_layer_level_text[3];
|
||||||
|
static char s_information_layer_count_text[6];
|
||||||
|
|
||||||
|
static void information_layer_update_proc(Layer *layer, GContext *ctx) {
|
||||||
|
GRect rect = layer_get_unobstructed_bounds(layer);
|
||||||
|
GFont font = resources_service_get_custom_font(CustomFontKonekoToro);
|
||||||
|
InformationLayerData *data = layer_get_data(s_information_layer);
|
||||||
|
|
||||||
|
int content_w = INFO_LAYER_ICON_WIDTH + INFO_LAYER_PADDING;
|
||||||
|
|
||||||
|
snprintf(s_information_layer_level_text, sizeof(s_information_layer_level_text), "%d",
|
||||||
|
data->level);
|
||||||
|
GSize text_size = graphics_text_layout_get_content_size(
|
||||||
|
s_information_layer_level_text, font, rect, GTextOverflowModeFill, GTextAlignmentLeft);
|
||||||
|
content_w += text_size.w;
|
||||||
|
|
||||||
|
#ifdef PBL_HEALTH
|
||||||
|
snprintf(s_information_layer_count_text, sizeof(s_information_layer_count_text), "%d",
|
||||||
|
data->steps);
|
||||||
|
text_size = graphics_text_layout_get_content_size(s_information_layer_count_text, font, rect,
|
||||||
|
GTextOverflowModeFill, GTextAlignmentLeft);
|
||||||
|
content_w += INFO_LAYER_ICON_WIDTH + INFO_LAYER_PADDING + text_size.w;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int content_x = (rect.size.w - content_w) / 2;
|
||||||
|
|
||||||
|
/* Draw the battery icon based on level percentage. */
|
||||||
|
graphics_context_set_compositing_mode(ctx, GCompOpSet);
|
||||||
|
|
||||||
|
GBitmap *battery_icon;
|
||||||
|
if (data->level < 20) {
|
||||||
|
battery_icon = resources_service_get_custom_icon(CustomIconBatteryEmpty);
|
||||||
|
} else if (data->level < 80) {
|
||||||
|
battery_icon = resources_service_get_custom_icon(CustomIconBatteryHalf);
|
||||||
|
} else {
|
||||||
|
battery_icon = resources_service_get_custom_icon(CustomIconBatteryFull);
|
||||||
|
}
|
||||||
|
|
||||||
|
GRect battery_rect_inside = GRect(0, 0, INFO_LAYER_ICON_WIDTH, rect.size.h);
|
||||||
|
GRect battery_rect = gbitmap_get_bounds(battery_icon);
|
||||||
|
grect_align(&battery_rect, &battery_rect_inside, GAlignCenter, true);
|
||||||
|
battery_rect.origin.x += content_x;
|
||||||
|
graphics_draw_bitmap_in_rect(ctx, battery_icon, battery_rect);
|
||||||
|
|
||||||
|
/* Draw the battery level in text. */
|
||||||
|
GRect text_rect =
|
||||||
|
GRect(content_x + INFO_LAYER_ICON_WIDTH + INFO_LAYER_PADDING, -4, text_size.w, text_size.h);
|
||||||
|
|
||||||
|
graphics_context_set_text_color(ctx, GColorBlack);
|
||||||
|
graphics_draw_text(ctx, s_information_layer_level_text, font, text_rect, GTextOverflowModeFill,
|
||||||
|
GTextAlignmentLeft, NULL);
|
||||||
|
|
||||||
|
#ifdef PBL_HEALTH
|
||||||
|
/* Draw the paws icon. */
|
||||||
|
GBitmap *paws_icon = resources_service_get_custom_icon(CustomIconPaws);
|
||||||
|
GRect paws_rect = gbitmap_get_bounds(paws_icon);
|
||||||
|
paws_rect.origin.x = content_x + text_rect.size.w;
|
||||||
|
graphics_draw_bitmap_in_rect(ctx, paws_icon, paws_rect);
|
||||||
|
|
||||||
|
/* Draw the step count in text. */
|
||||||
|
text_rect = GRect(paws_rect.origin.x + INFO_LAYER_ICON_WIDTH + INFO_LAYER_PADDING, -4,
|
||||||
|
text_size.w, text_size.h);
|
||||||
|
graphics_context_set_text_color(ctx, GColorBlack);
|
||||||
|
graphics_draw_text(ctx, s_information_layer_count_text, font, text_rect, GTextOverflowModeFill,
|
||||||
|
GTextAlignmentLeft, NULL);
|
||||||
|
#endif // PBL_HEALTH
|
||||||
|
}
|
||||||
|
|
||||||
|
static void battery_state_service_callback(BatteryChargeState charge) {
|
||||||
|
InformationLayerData *data = layer_get_data(s_information_layer);
|
||||||
|
data->level = charge.charge_percent;
|
||||||
|
layer_mark_dirty(s_information_layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void information_layer_init(Layer *layer, int y) {
|
||||||
|
GRect rect = layer_get_unobstructed_bounds(layer);
|
||||||
|
|
||||||
|
s_information_layer = layer_create_with_data(GRect(0, y, rect.size.w, INFO_LAYER_HEIGHT),
|
||||||
|
sizeof(InformationLayerData));
|
||||||
|
|
||||||
|
InformationLayerData *data = layer_get_data(s_information_layer);
|
||||||
|
data->level = battery_state_service_peek().charge_percent;
|
||||||
|
data->steps = PBL_IF_HEALTH_ELSE(health_service_sum_today(HealthMetricStepCount), 0);
|
||||||
|
|
||||||
|
layer_set_update_proc(s_information_layer, information_layer_update_proc);
|
||||||
|
layer_add_child(layer, s_information_layer);
|
||||||
|
|
||||||
|
battery_state_service_subscribe(battery_state_service_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void information_layer_tick(void) {
|
||||||
|
#ifdef PBL_HEALTH
|
||||||
|
InformationLayerData *data = layer_get_data(s_information_layer);
|
||||||
|
data->steps = health_service_sum_today(HealthMetricStepCount);
|
||||||
|
layer_mark_dirty(s_information_layer);
|
||||||
|
#endif // PBL_HEALTH
|
||||||
|
}
|
||||||
|
|
||||||
|
void information_layer_deinit(void) {
|
||||||
|
layer_destroy(s_information_layer);
|
||||||
|
}
|
||||||
10
src/c/information_layer.h
Normal file
10
src/c/information_layer.h
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef INFORMATION_LAYER_H_
|
||||||
|
#define INFORMATION_LAYER_H_
|
||||||
|
|
||||||
|
#include <pebble.h>
|
||||||
|
|
||||||
|
void information_layer_init(Layer *layer, int y);
|
||||||
|
void information_layer_tick(void);
|
||||||
|
void information_layer_deinit(void);
|
||||||
|
|
||||||
|
#endif // INFORMATION_LAYER_H_
|
||||||
|
|
@ -2,12 +2,14 @@
|
||||||
#include "date_layer.h"
|
#include "date_layer.h"
|
||||||
#include "character_layer.h"
|
#include "character_layer.h"
|
||||||
#include "clock_layer.h"
|
#include "clock_layer.h"
|
||||||
|
#include "information_layer.h"
|
||||||
|
|
||||||
static Window *s_main_window;
|
static Window *s_main_window;
|
||||||
|
|
||||||
static void main_window_tick(struct tm *time, TimeUnits units) {
|
static void main_window_tick(struct tm *time, TimeUnits units) {
|
||||||
date_layer_tick();
|
date_layer_tick();
|
||||||
clock_layer_tick();
|
clock_layer_tick();
|
||||||
|
information_layer_tick();
|
||||||
character_layer_tick();
|
character_layer_tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -15,7 +17,11 @@ static void main_window_load(Window *window) {
|
||||||
Layer *layer = window_get_root_layer(window);
|
Layer *layer = window_get_root_layer(window);
|
||||||
|
|
||||||
date_layer_init(layer, 0);
|
date_layer_init(layer, 0);
|
||||||
clock_layer_init(layer, 40);
|
clock_layer_init(layer, 30);
|
||||||
|
|
||||||
|
GRect clock_layer_rect = clock_layer_get_bounds();
|
||||||
|
information_layer_init(layer, 30 + clock_layer_rect.size.h + 4);
|
||||||
|
|
||||||
character_layer_init(layer);
|
character_layer_init(layer);
|
||||||
|
|
||||||
tick_timer_service_subscribe(SECOND_UNIT, main_window_tick);
|
tick_timer_service_subscribe(SECOND_UNIT, main_window_tick);
|
||||||
|
|
@ -26,6 +32,7 @@ static void main_window_unload(Window *window) {
|
||||||
|
|
||||||
clock_layer_deinit();
|
clock_layer_deinit();
|
||||||
date_layer_deinit();
|
date_layer_deinit();
|
||||||
|
information_layer_deinit();
|
||||||
character_layer_deinit();
|
character_layer_deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,25 +8,41 @@ typedef struct ResourcesService {
|
||||||
GFont font_toro;
|
GFont font_toro;
|
||||||
GBitmap *character_even;
|
GBitmap *character_even;
|
||||||
GBitmap *character_odd;
|
GBitmap *character_odd;
|
||||||
|
GBitmap *icon_battery_empty;
|
||||||
|
GBitmap *icon_battery_half;
|
||||||
|
GBitmap *icon_battery_full;
|
||||||
|
GBitmap *icon_paws;
|
||||||
} ResourcesService;
|
} ResourcesService;
|
||||||
|
|
||||||
static ResourcesService *s_resources_service;
|
static ResourcesService *s_resources_service;
|
||||||
|
|
||||||
void resources_service_init(void) {
|
void resources_service_init(void) {
|
||||||
s_resources_service = malloc(sizeof(ResourcesService));
|
s_resources_service = malloc(sizeof(ResourcesService));
|
||||||
|
|
||||||
s_resources_service->font_koneko_toro =
|
s_resources_service->font_koneko_toro =
|
||||||
fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_KONEKO_TORO));
|
fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_KONEKO_TORO));
|
||||||
s_resources_service->font_toro =
|
s_resources_service->font_toro =
|
||||||
fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_TORO));
|
fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_TORO));
|
||||||
|
|
||||||
s_resources_service->character_even = gbitmap_create_with_resource(RESOURCE_ID_CHARACTER_EVEN);
|
s_resources_service->character_even = gbitmap_create_with_resource(RESOURCE_ID_CHARACTER_EVEN);
|
||||||
s_resources_service->character_odd = gbitmap_create_with_resource(RESOURCE_ID_CHARACTER_ODD);
|
s_resources_service->character_odd = gbitmap_create_with_resource(RESOURCE_ID_CHARACTER_ODD);
|
||||||
|
|
||||||
|
s_resources_service->icon_battery_empty =
|
||||||
|
gbitmap_create_with_resource(RESOURCE_ID_ICON_BATTERY_EMPTY);
|
||||||
|
s_resources_service->icon_battery_full =
|
||||||
|
gbitmap_create_with_resource(RESOURCE_ID_ICON_BATTERY_FULL);
|
||||||
|
s_resources_service->icon_battery_half =
|
||||||
|
gbitmap_create_with_resource(RESOURCE_ID_ICON_BATTERY_HALF);
|
||||||
|
s_resources_service->icon_paws = gbitmap_create_with_resource(RESOURCE_ID_ICON_PAWS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resources_service_deinit(void) {
|
void resources_service_deinit(void) {
|
||||||
fonts_unload_custom_font(s_resources_service->font_koneko_toro);
|
fonts_unload_custom_font(s_resources_service->font_koneko_toro);
|
||||||
fonts_unload_custom_font(s_resources_service->font_toro);
|
fonts_unload_custom_font(s_resources_service->font_toro);
|
||||||
|
|
||||||
gbitmap_destroy(s_resources_service->character_even);
|
gbitmap_destroy(s_resources_service->character_even);
|
||||||
gbitmap_destroy(s_resources_service->character_odd);
|
gbitmap_destroy(s_resources_service->character_odd);
|
||||||
|
|
||||||
free(s_resources_service);
|
free(s_resources_service);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -37,6 +53,20 @@ GBitmap *resources_service_get_character(int ticks) {
|
||||||
return s_resources_service->character_odd;
|
return s_resources_service->character_odd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GBitmap *resources_service_get_custom_icon(CustomIcon icon) {
|
||||||
|
switch (icon) {
|
||||||
|
case CustomIconBatteryEmpty:
|
||||||
|
return s_resources_service->icon_battery_empty;
|
||||||
|
case CustomIconBatteryFull:
|
||||||
|
return s_resources_service->icon_battery_full;
|
||||||
|
case CustomIconBatteryHalf:
|
||||||
|
return s_resources_service->icon_battery_half;
|
||||||
|
case CustomIconPaws:
|
||||||
|
return s_resources_service->icon_paws;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
GFont resources_service_get_custom_font(CustomFont font) {
|
GFont resources_service_get_custom_font(CustomFont font) {
|
||||||
switch (font) {
|
switch (font) {
|
||||||
case CustomFontKonekoToro:
|
case CustomFontKonekoToro:
|
||||||
|
|
@ -44,5 +74,5 @@ GFont resources_service_get_custom_font(CustomFont font) {
|
||||||
case CustomFontToro:
|
case CustomFontToro:
|
||||||
return s_resources_service->font_toro;
|
return s_resources_service->font_toro;
|
||||||
}
|
}
|
||||||
return NULL;
|
return fonts_get_system_font(FONT_KEY_FONT_FALLBACK);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,18 @@ typedef enum CustomFont {
|
||||||
CustomFontToro
|
CustomFontToro
|
||||||
} CustomFont;
|
} CustomFont;
|
||||||
|
|
||||||
|
typedef enum CustomIcon {
|
||||||
|
CustomIconBatteryEmpty,
|
||||||
|
CustomIconBatteryFull,
|
||||||
|
CustomIconBatteryHalf,
|
||||||
|
CustomIconPaws
|
||||||
|
} CustomIcon;
|
||||||
|
|
||||||
void resources_service_init(void);
|
void resources_service_init(void);
|
||||||
void resources_service_deinit(void);
|
void resources_service_deinit(void);
|
||||||
|
|
||||||
GBitmap *resources_service_get_character(int ticks);
|
GBitmap *resources_service_get_character(int ticks);
|
||||||
|
GBitmap *resources_service_get_custom_icon(CustomIcon icon);
|
||||||
GFont resources_service_get_custom_font(CustomFont font);
|
GFont resources_service_get_custom_font(CustomFont font);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue