Source

pebble / zulu / src / zulu.c

/** \file
 * Sun up/sundown clock with 24 hour face and moon phase.
 *
 */
#include "pebble_os.h"
#include "pebble_app.h"
#include "pebble_fonts.h"
#include "pebble_th.h"

#define UUID { 0x06, 0x97, 0xE5, 0x7F, 0x60, 0xF7, 0x43, 0xC5, 0x80, 0xC4, 0x35, 0x9D, 0xB2, 0x7E, 0xCD, 0xEE }

PBL_APP_INFO(
	UUID,
	"Moonphase",
	"hudson",
	1, 0, // Version
	RESOURCE_ID_IMAGE_MENU_ICON,
	APP_INFO_WATCH_FACE
);


// Local timezone GMT offset
static const int gmt_offset = -5;

static Window window;
static Layer graphics_layer;
static PblTm now;
static GFont font_thin;
static GFont font_thick;

// Circle points computed at startup and the path is dynamically adjuste
#define NUM_POINTS 256
static GPoint circle_points[NUM_POINTS];
static GPath circle_path;
static GPathInfo circle_info = { NUM_POINTS, &circle_points };


static void
graphics_layer_update(
        Layer * const me,
        GContext * ctx
)
{
	(void) me;

	const int w = me->bounds.size.w;
	const int h = me->bounds.size.h;

	graphics_context_set_stroke_color(ctx, GColorWhite);
	graphics_context_set_fill_color(ctx, GColorWhite);

	// Draw the outline circle
	graphics_draw_circle(ctx, GPoint(w/2,h/2), w/2-1);

	// Compute the sun up / sun down time and
	// draw the semi-circle
	//int sun_up = 64;
	//int sun_down = 190;

	circle_path.num_points = 90;
	//circle_path.points = &circle_points[sun_up];
	gpath_draw_filled(ctx, &circle_path);

#if 0
	const timezone_t * const tz = container_of(me, timezone_t, layer);

	const int orig_hour = now.tm_hour;

	now.tm_hour += tz->offset - gmt_offset;
	if (now.tm_hour > 24)
		now.tm_hour -= 24;
	if (now.tm_hour < 0)
		now.tm_hour += 24;

	char buf[32];
	string_format_time(
		buf,
		sizeof(buf),
		"%H:%M",
		&now
	);


	const int night_time = (now.tm_hour > 18 || now.tm_hour < 6);
	now.tm_hour = orig_hour;

	const int w = me->bounds.size.w;
	const int h = me->bounds.size.h;
		
	// it is night there, draw in black video
	graphics_context_set_fill_color(ctx, night_time ? GColorBlack : GColorWhite);
	graphics_context_set_text_color(ctx, !night_time ? GColorBlack : GColorWhite);
	graphics_fill_rect(ctx, GRect(0, 0, w, h), 0, 0);

	graphics_text_draw(ctx,
		tz->name,
		font_thin,
		GRect(0, 0, w, h/3),
		GTextOverflowModeTrailingEllipsis,
		GTextAlignmentCenter,
		NULL
	);

	graphics_text_draw(ctx,
		buf,
		font_thick,
		GRect(0, h/3, w, 2*h/3),
		GTextOverflowModeTrailingEllipsis,
		GTextAlignmentCenter,
		NULL
	);
#endif
}


/** Called once per minute */
static void
handle_tick(
	AppContextRef ctx,
	PebbleTickEvent * const event
)
{
	(void) ctx;

	now = *event->tick_time;

	layer_mark_dirty(&graphics_layer);
}


static void
handle_init(
	AppContextRef ctx
)
{
	(void) ctx;
	const int w = PEBBLE_SCREEN_WIDTH - 4;
	const int h = PEBBLE_SCREEN_WIDTH - 4;

	// Compute the points around the circle
	for (int i = 0 ; i < NUM_POINTS ; i++)
	{
		const uint32_t angle = (i * TRIG_MAX_ANGLE) / NUM_POINTS;
		const int s = sin_lookup(angle);
		const int c = cos_lookup(angle);
		circle_points[i].x = (w/2) + ((w/2) * s) / 0x10000;
		circle_points[i].y = (h/2) - ((h/2) * c) / 0x10000;
	}

	gpath_init(&circle_path, &circle_info);

	get_time(&now);

	window_init(&window, "Main");
	window_stack_push(&window, true);
	window_set_background_color(&window, GColorBlack);

	resource_init_current_app(&RESOURCES);

	//font_thin = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_ARIAL_16));
	font_thick = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_ARIAL_BLACK_30));

	layer_init(&graphics_layer, GRect(0, 0, w, h));
	layer_add_child(&window.layer, &graphics_layer);
	graphics_layer.update_proc = graphics_layer_update;
	layer_mark_dirty(&graphics_layer);
}


static void
handle_deinit(
	AppContextRef ctx
)
{
	(void) ctx;

	fonts_unload_custom_font(font_thin);
	fonts_unload_custom_font(font_thick);
}


void
pbl_main(
	void * const params
)
{
	PebbleAppHandlers handlers = {
		.init_handler	= &handle_init,
		.deinit_handler = &handle_deinit,
		.tick_info	= {
			.tick_handler = &handle_tick,
			.tick_units = MINUTE_UNIT,
		},
	};

	app_event_loop(params, &handlers);
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.