pebble / hoelaat / src / nederlands.c

/** \file
 * Word clock, with Dutch time.
 *
 * Four lines:
 *
 * minutes (or blank)
 * over/voor/half (or blank)
 * HOUR (in bold)
 * 's ochtends / 's middags 
 *
 * \todo: When any line changes, it is pushed to the side
 *
 * een uur
 * een over een
 * kwart over een
 * tien voor half twee
 * half twee
 * vijf over half twee
 * kwart voor twee
 * 
 * And 's ochtends, 's middags, 's avonds, 's nachts
 * vier uur
 * half vier 
 */
#include "pebble_os.h"
#include "pebble_app.h"
#include "pebble_fonts.h"
#include "pebble_th.h"

static Window window;
static GFont font_thin;
static GFont font_thick;

typedef struct
{
	TextLayer layer;
	PropertyAnimation anim;
	const char * text;
	const char * old_text;
} word_t;

static word_t min_word;
static word_t rel_word;
static word_t hour_word;
static word_t ampm_word;


static const char *nums[] = {
	"",
	"één",
	"twee",
	"drie",
	"vier",
	"vijf",
	"zes",
	"zeven",
	"acht",
	"negen",
	"tien",
	"elf",
	"twaalf",
	"dertien",
	"veertien",
	"kwart",
};

static const char *
min_string(
	int i
)
{
	return nums[i];
}


static const char *
hour_string(
	int h
)
{
	// only if it is actually midnight, not "before midnight"
	if (h == 0)
		return "midder-\nnacht";

	if (h == 12)
		return "middag";

	if (h < 12)
		return nums[h];
	else
		return nums[h - 12];
}


static void
nederlands_format(
	int hour,
	int min
)
{
	if (min == 0)
	{
		min_word.text = "";
		rel_word.text = "";
	} else
	if (min <= 15)
	{
		// over the hour
		min_word.text = min_string(min);
		rel_word.text = "over";
	} else
	if (min < 30)
	{
		// over the kwart
		min_word.text = min_string(30 - min);
		rel_word.text = "voor half";
		hour++;
	} else
	if (min == 30)
	{
		// just the half
		min_word.text = "";
		rel_word.text = "half";
		hour++;
	} else
	if (min < 45)
	{
		// over the half
		min_word.text = min_string(min - 30);
		rel_word.text = "over half";
		hour++;
	} else
	if (min == 45)
	{
		// just the kwart
		min_word.text = "";
		rel_word.text = "kwart voor";
		hour++;
	} else
	if (min < 60)
	{
		// over the kwart
		min_word.text = min_string(60 - min);
		rel_word.text = "voor";
		hour++;
	}

	hour_word.text = hour_string(hour);

	// at midnight and noon do not display an am/pm notation
	// but don't say "before midnight"
	if (hour == 0 || hour == 12)
	{
		// nothing to do
		ampm_word.text = "";
	} else
	if (hour < 6)
		ampm_word.text = "'s nachts";
	else
	if (hour <= 12)
		ampm_word.text = "'s morgens";
	else
	if (hour <= 17)
		ampm_word.text = "'s middags";
	else
	if (hour <= 24)
		ampm_word.text = "'s avonds";
}


PBL_APP_INFO(
	"Hoe laat is het?",
	"hudson",
	2, // Version
	RESOURCE_ID_IMAGE_MENU_ICON,
	APP_INFO_WATCH_FACE
);



static void
update_word(
	word_t * const word
)
{
	text_layer_set_text(&word->layer, word->text);
	if (word->text != word->old_text)
		animation_schedule(&word->anim.animation);
}


/** Called once per minute */
static void
handle_tick(
	AppContextRef ctx,
	PebbleTickEvent * const event
)
{
	(void) ctx;
	const PblTm * const ptm = event->tick_time;

	int hour = ptm->tm_hour;
	int min = ptm->tm_min;

	ampm_word.old_text = ampm_word.text;
	hour_word.old_text = hour_word.text;
	rel_word.old_text = rel_word.text;
	min_word.old_text = min_word.text;

	nederlands_format(hour,  min);

/*
	string_format_time(
		time_buffer,
		sizeof(time_buffer),
		"%H:%M",
		event->tick_time
	);
*/

	update_word(&ampm_word);
	update_word(&hour_word);
	update_word(&rel_word);
	update_word(&min_word);
}


static void
text_layer(
	word_t * word,
	GRect frame,
	GFont font
)
{
	text_layer_setup(&window, &word->layer, frame, font);

	GRect frame_right = frame;
	frame_right.origin.x = 150;

	property_animation_init_layer_frame(
		&word->anim,
		&word->layer.layer,
		&frame_right,
		&frame
	);

	animation_set_duration(&word->anim.animation, 500);
	animation_set_curve(&word->anim.animation, AnimationCurveEaseIn);
}


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

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

	resource_init_current_app(&RESOURCES);

	int y = 15;
	int h = 30;

	font_thin = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_ARIAL_28));
	font_thick = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_ARIAL_BLACK_30));

	// Stack top to bottom.  Note that the hour can take up
	// two rows at midnight.
	text_layer(&ampm_word, GRect(4, y + 3*h, 144, h+8), font_thin);
	text_layer(&hour_word, GRect(4, y + 2*h, 144, 2*h+8), font_thick);
	text_layer(&rel_word, GRect(4, y + 1*h, 144, h+8), font_thin);
	text_layer(&min_word, GRect(4, y + 0*h, 144, h+8), font_thin);

}


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.