Source

pebble / th10 / src / th10.c

/** \file
 * TH10 -- Torgoen T10 analog style
 *
 */
#include "pebble_os.h"
#include "pebble_app.h"
#include "pebble_fonts.h"
#include "pebble_th.h"

#define UUID { 0xDD, 0xD6, 0x07, 0x2A, 0x2D, 0x0B, 0x4D, 0x79, 0x99, 0x6D, 0xDC, 0x69, 0xD4, 0x62, 0xB8, 0x5B }

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


static Window window;
static Layer hand_layer;
static Layer bg_layer;
static PblTm now;
static GFont font_time;

static int use_24hour;


// Dimensions of the watch face
#define W PEBBLE_SCREEN_WIDTH
#define H PEBBLE_SCREEN_HEIGHT
#define R (W/2 - 2)

// Hour hand
static GPath hour_path;
static GPoint hour_points[] = {
	{  -8, -20 },
	{ -10, -40 },
	{   0, -60 },
	{ +10, -40 },
	{  +8, -20 },
	{  -8, -20 },
};

// Minute hand
static GPath minute_path;
static GPoint minute_points[] = {
	{ -5, -20 },
	{ -7, -60 },
	{  0, -76 },
	{ +7, -60 },
	{ +5, -20 },
	{ -5, -20 },
};

// Hour hand ticks around the circle (slightly shorter)
static GPath hour_tick_path;
static GPoint hour_tick_points[] = {
	{ -3, 70 },
	{ +3, 70 },
	{ +3, 84 },
	{ -3, 84 },
};

// Non-hour major ticks around the circle
static GPath major_tick_path;
static GPoint major_tick_points[] = {
	{ -3, 60 },
	{ +3, 60 },
	{ +3, 84 },
	{ -3, 84 },
};

// Non-major ticks around the circle; will be drawn as lines
static GPath minor_tick_path;
static GPoint minor_tick_points[] = {
	{ 0, 76 },
	{ 0, 84 },
};

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

	// Draw the minute hand outline in black and filled with white
	int minute_angle = (now.tm_min * TRIG_MAX_ANGLE) / 60;

	gpath_rotate_to(&minute_path, minute_angle);
	graphics_context_set_stroke_color(ctx, GColorBlack);
	gpath_draw_outline(ctx, &minute_path);
	graphics_context_set_fill_color(ctx, GColorWhite);
	gpath_draw_filled(ctx, &minute_path);

	// Draw the hour hand outline in black and filled with white
	// above the minute hand
	int hour_angle;
	if (use_24hour)
	{
		hour_angle = ((now.tm_hour * 60 + now.tm_min) * TRIG_MAX_ANGLE) / (60 * 24);
	} else {
		int hour = now.tm_hour;
		if (hour > 12)
			hour -= 12;
		hour_angle = ((hour * 60 + now.tm_min) * TRIG_MAX_ANGLE) / (60 * 12);
	}

	gpath_rotate_to(&hour_path, hour_angle);
	graphics_context_set_stroke_color(ctx, GColorBlack);
	gpath_draw_outline(ctx, &hour_path);
	graphics_context_set_fill_color(ctx, GColorWhite);
	gpath_draw_filled(ctx, &hour_path);

}


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

	now = *event->tick_time;

	layer_mark_dirty(&hand_layer);
}


/** Draw the initial background image */
static void
bg_layer_update(
        Layer * const me,
        GContext * ctx
)
{
	(void) me;

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

	// Draw the center circle
	graphics_draw_circle(ctx, GPoint(W/2,H/2), 3);

	// Draw the outside marks
	for (int min = 0 ; min < 60 ; min++)
	{
		const int angle = (min * TRIG_MAX_ANGLE) / 60;
		if ((min % 15) == 0)
		{
			gpath_rotate_to(&hour_tick_path, angle);
			gpath_draw_filled(ctx, &hour_tick_path);
		} else
		if ((min % 5) == 0)
		{
			gpath_rotate_to(&major_tick_path, angle);
			gpath_draw_filled(ctx, &major_tick_path);
		} else {
			gpath_rotate_to(&minor_tick_path, angle);
			gpath_draw_outline(ctx, &minor_tick_path);
		}
	}

	// And the large labels
	graphics_text_draw(ctx,
		use_24hour ? "24" : "12",
		font_time,
		GRect(W/2-30,4,60,50),
		GTextOverflowModeTrailingEllipsis,
		GTextAlignmentCenter,
		NULL
	);

	graphics_text_draw(ctx,
		use_24hour ? "06" : "3",
		font_time,
		GRect(W/2,H/2-26,70,50),
		GTextOverflowModeTrailingEllipsis,
		GTextAlignmentRight,
		NULL
	);

	graphics_text_draw(ctx,
		use_24hour ? "12" : "6",
		font_time,
		GRect(W/2-30,110,60,50),
		GTextOverflowModeTrailingEllipsis,
		GTextAlignmentCenter,
		NULL
	);

	graphics_text_draw(ctx,
		use_24hour ? "18" : "9",
		font_time,
		GRect(W/2-70,H/2-26,60,50),
		GTextOverflowModeTrailingEllipsis,
		GTextAlignmentLeft,
		NULL
	);
}

#define GPATH_INIT(PATH, POINTS) ({ \
	GPathInfo __info = { sizeof(POINTS) / sizeof(*POINTS), POINTS }; \
	gpath_init(PATH, &__info); \
	})

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

	GPATH_INIT(&hour_path, hour_points);
	gpath_move_to(&hour_path, GPoint(W/2,H/2));

	GPATH_INIT(&minute_path, minute_points);
	gpath_move_to(&minute_path, GPoint(W/2,H/2));

	GPATH_INIT(&major_tick_path, major_tick_points);
	gpath_move_to(&major_tick_path, GPoint(W/2,H/2));

	GPATH_INIT(&hour_tick_path, hour_tick_points);
	gpath_move_to(&hour_tick_path, GPoint(W/2,H/2));

	GPATH_INIT(&minor_tick_path, minor_tick_points);
	gpath_move_to(&minor_tick_path, GPoint(W/2,H/2));

	get_time(&now);
	use_24hour = clock_is_24h_style();

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

	resource_init_current_app(&RESOURCES);

	font_time = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_GILLSANS_40));

	layer_init(&bg_layer, GRect(0, 0, W, H));
	layer_add_child(&window.layer, &bg_layer);
	bg_layer.update_proc = bg_layer_update;
	layer_mark_dirty(&bg_layer);

	layer_init(&hand_layer, GRect(0, 0, W, H));
	layer_add_child(&window.layer, &hand_layer);
	hand_layer.update_proc = hand_layer_update;
	layer_mark_dirty(&hand_layer);
}


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

	fonts_unload_custom_font(font_time);
}


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.