Source

pebble / worldmap / src / worldmap.c

Trammell Hudson 665f799 
Trammell Hudson acbc365 



Trammell Hudson 01e8086 


Trammell Hudson 665f799 




Trammell Hudson 01e8086 


Trammell Hudson 40ae272 

Trammell Hudson 665f799 
Trammell Hudson 40ae272 
Trammell Hudson bf92fdd 
Trammell Hudson 665f799 
Trammell Hudson 40ae272 
Trammell Hudson 665f799 





Trammell Hudson 01e8086 
Trammell Hudson 665f799 


Trammell Hudson 63fbbeb 
Trammell Hudson 665f799 
Trammell Hudson 01e8086 
























Trammell Hudson 665f799 






Trammell Hudson bf92fdd 









Trammell Hudson 665f799 
Trammell Hudson bf92fdd 


































Trammell Hudson 01e8086 
Trammell Hudson bf92fdd 

Trammell Hudson 665f799 









Trammell Hudson bf92fdd 
Trammell Hudson 665f799 







Trammell Hudson 1913f76 
Trammell Hudson 665f799 



Trammell Hudson 1913f76 

Trammell Hudson 665f799 

Trammell Hudson 1913f76 






Trammell Hudson 665f799 






























Trammell Hudson bf92fdd 

Trammell Hudson 665f799 




Trammell Hudson 1913f76 


Trammell Hudson 665f799 

Trammell Hudson 1913f76 

Trammell Hudson 665f799 
Trammell Hudson 01e8086 




Trammell Hudson 665f799 







Trammell Hudson 1913f76 

Trammell Hudson 665f799 













Trammell Hudson bf92fdd 
Trammell Hudson 76e1449 

Trammell Hudson 665f799 
Trammell Hudson bf92fdd 
Trammell Hudson 665f799 



/** \file
 * World map clock.
 *
 * Image from: http://commons.wikimedia.org/wiki/File:Northern_Hemisphere_Azimuthal_projections.svg
 *
 * Feature ideas:
 * - Sunset/sunrise terminator markers (seasonally adjusted)
 * - Moon phase?
 */
#include <pebble_os.h>
#include <pebble_app.h>
#include <pebble_fonts.h>

// Update once per second to test things
#undef CONFIG_DEBUG

#define UUID {0x38, 0x38, 0x8B, 0x74, 0xB3, 0xD1, 0x42, 0x1F, 0x90, 0xFA, 0xBF, 0x34, 0xED, 0xB3, 0xB3, 0x8F}

PBL_APP_INFO(
	UUID,
	"Polar Map",
	"hudson",
	2, 0, // Version
	RESOURCE_ID_IMAGE_MENU_ICON,
	APP_INFO_WATCH_FACE
);

static Window window;
static RotBmpPairContainer map_container;
static Layer marker_layer;

static char time_text[8];
static TextLayer time_layer;
static const int gmt_offset = -4; // hours from GMT

/** Update the line markers. */
static void
marker_layer_update(
        Layer * const me,
        GContext * ctx
)
{
	(void) me;

	for (int i = 0 ; i < 168/2 ; i += 8)
	{
		graphics_draw_line(
			ctx,
			GPoint(144/2,168/2 + i),
			GPoint(144/2,168/2 + i + 1)
		);
	}
}



/** Called once per minute.
 * Update the map rotation angle and flag it as dirty to force
 * a redraw..
 */
static void
handle_tick(
	AppContextRef ctx,
	PebbleTickEvent * const event
)
{
	(void) ctx;
#ifdef CONFIG_DEBUG
	// Fake the time
	PblTm real_ptm = { .tm_hour = 17, .tm_min = 27 };
	PblTm * ptm = &real_ptm;
	static int h = 0;
	if (++h == 24)
		h = 0;
	ptm->tm_hour = h;
#else
	// real time
	const PblTm * const ptm = event->tick_time;
#endif

	// Adjust hour by GMT offset and reverse angle
	// Note that this image is has GMT "noon" at the bottom.
	// (world rotates "backwards" relative to the sun)
	const int32_t angle = 0
		+ (TRIG_MAX_ANGLE * gmt_offset) / 24
		+ (TRIG_MAX_ANGLE * (ptm->tm_hour + gmt_offset)) / 24
		+ (TRIG_MAX_ANGLE * ptm->tm_min) / (60 * 24)
		;

	const int q = (((angle + TRIG_MAX_ANGLE) & TRIG_MAX_RATIO) * 32) / TRIG_MAX_ANGLE;

	// Check for quadrants to determine where to move the time
	if (q <= 7)
	{
		// Upper left
		time_layer.layer.frame.origin = GPoint(0,-6);
	} else
	if (q <= 15)
	{
		// Lower left
		time_layer.layer.frame.origin = GPoint(0,150);
	} else
	if (q <= 23)
	{
		// Lower right
		time_layer.layer.frame.origin = GPoint(90, 150);
	} else
	if (q <= 31)
	{
		// Upper right
		time_layer.layer.frame.origin = GPoint(90, -6);
	}

#ifdef CONFIG_DEBUG
	ptm->tm_min = q;
#endif

	string_format_time(
		time_text,
		sizeof(time_text),
		"%H:%M",
		ptm
	);

	text_layer_set_text(&time_layer, time_text);

	rotbmp_pair_layer_set_angle(&map_container.layer, -angle);
	layer_mark_dirty(&map_container.layer.layer);
}


static void
text_layer(
	TextLayer * layer,
	GRect frame,
	GFont font
)
{
	text_layer_init(layer, frame);
	text_layer_set_text(layer, "");
#if 0
	// white bg to help with layout
	text_layer_set_text_color(layer, GColorBlack);
	text_layer_set_background_color(layer, GColorWhite);
#else
	// black bg for real
	text_layer_set_text_color(layer, GColorWhite);
	text_layer_set_background_color(layer, GColorBlack);
#endif

	text_layer_set_font(layer, font);

	layer_add_child(&window.layer, &layer->layer);
}


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

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

	resource_init_current_app(&RESOURCES);

	// This doesn't need the transparency, but there is no
	// rotbmp that isn't a pair?
	rotbmp_pair_init_container(
		RESOURCE_ID_IMAGE_MAP_WHITE,
		RESOURCE_ID_IMAGE_MAP_BLACK,
		&map_container
	);

	//map_container.layer.compositing_mode = GCompOpAssignInverted;
	//map_container.layer.compositing_mode = GCompOpAssign;

	rotbmp_pair_layer_set_src_ic(&map_container.layer, GPoint(100,100));

	// No dest_ic routines?  Relocate the point of rotation to
	// the center of the map for both layers.
	map_container.layer.white_layer.dest_ic = GPoint(144/2, 168/2);
	map_container.layer.black_layer.dest_ic = GPoint(144/2, 168/2);

	layer_add_child(&window.layer, &map_container.layer.layer);

	GFont font = fonts_load_custom_font(resource_get_handle(
		RESOURCE_ID_FONT_SOURCECODEPRO_LIGHT_18));

	text_layer(
		&time_layer,
		GRect(90, -6, 60, 20),
		font
	);

	layer_init(&marker_layer, GRect(0, 0, 144, 168));
	marker_layer.update_proc = marker_layer_update;
	layer_add_child(&window.layer, &marker_layer);
	layer_mark_dirty(&marker_layer);
}


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

	rotbmp_pair_deinit_container(&map_container);
}


void
pbl_main(
	void * const params
)
{
	PebbleAppHandlers handlers = {
		.init_handler	= handle_init,
		.deinit_handler	= handle_deinit,
		.tick_info	= {
			.tick_handler = handle_tick,
#ifdef CONFIG_DEBUG
			.tick_units = SECOND_UNIT,
#else
			.tick_units = MINUTE_UNIT,
#endif
		},
	};

	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.