/*
* App uses 2 windows:
* main window with the menu
* option window with the title and the modes
*/
#include <pebble.h>
#define NUM_ROWS 3
#define NUM_MODES 2
typedef struct {
char *title;
char *subtitle;
} ROW;
// Options to choose from menu.
static ROW options[] = {
{ .title = "LED 1", .subtitle = "Change led 1" },
{ .title = "LED 2", .subtitle = "Change led 2" },
{ .title = "LED 3", .subtitle = "Change led 3" }
};
// Modes that LED's can be in.
static char *s_textlayer_modes[] = {
"off",
"on"
};
// Remembers modes of LED's when you change rows
static int s_current_modes[] = {
0,0,0
};
static Window *s_main_window, *s_option_window;
static MenuLayer *s_menu_layer;
static TextLayer *s_text_layer;
static TextLayer *s_title, *s_mode;
// Store the index of the current row.
static int s_current_option;
static void inbox_received_callback(DictionaryIterator *iterator, void *context) {
APP_LOG(APP_LOG_LEVEL_INFO, "Inbox Received!");
}
static void inbox_dropped_callback(AppMessageResult reason, void* context) {
APP_LOG(APP_LOG_LEVEL_ERROR, "Message dropped!");
}
static void outbox_failed_callback(DictionaryIterator *iterator, AppMessageResult reason, void *context) {
APP_LOG(APP_LOG_LEVEL_ERROR, "Outbox send failed!");
}
static void outbox_sent_callback(DictionaryIterator *iterator, void *context) {
APP_LOG(APP_LOG_LEVEL_INFO, "Outbox send success!");
}
// Get number of rows
static uint16_t get_num_rows(struct MenuLayer* menu_layer, uint16_t section_index, void *callback_context) {
return NUM_ROWS;
}
// Draw rows of menu.
static void draw_row(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *callback_context) {
ROW *row_array = (ROW*) callback_context;
ROW *this_row = &row_array[cell_index->row];
menu_cell_basic_draw(ctx, cell_layer, this_row->title, this_row->subtitle, NULL);
}
// What to do when a row is clicked
static void select_click(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context) {
s_current_option = cell_index->row;
window_stack_push(s_option_window, true);
}
// Load main menu.
static void main_window_load(Window *window) {
Layer *window_layer = window_get_root_layer(window);
s_menu_layer = menu_layer_create(layer_get_bounds(window_layer));
menu_layer_set_callbacks(s_menu_layer, options, (MenuLayerCallbacks) {
.get_num_rows = get_num_rows,
.draw_row = draw_row,
.select_click = select_click
});
menu_layer_set_click_config_onto_window(s_menu_layer, window);
layer_add_child(window_layer, menu_layer_get_layer(s_menu_layer));
}
// Unload main menu
static void main_window_unload(Window *window) {
menu_layer_destroy(s_menu_layer);
}
// Update the option window with title and mode
static void show_selected_title_and_mode() {
ROW *choice = &options[s_current_option];
// Update the title
text_layer_set_text(s_title, options[s_current_option].title);
//Somehow get message of whether the led is currently on or off?
//That would be nice
text_layer_set_text(s_mode, s_textlayer_modes[s_current_modes[s_current_option]]);
}
// What to do when the select button is pressed. Cycle through modes and should send message to turn on/off LED
static void select_click_handler(ClickRecognizerRef recognizer, void *context) {
s_current_modes[s_current_option]++;
if ((unsigned)s_current_modes[s_current_option] >= NUM_MODES) {
s_current_modes[s_current_option] = 0;
}
DictionaryIterator *iterator;
app_message_outbox_begin(&iterator);
int key1 = 1;
int value1 = s_current_option;
dict_write_int(iterator, key1, &value1, sizeof(int), true);
int key2 = 2;
int value2 = s_current_modes[s_current_option];
dict_write_int(iterator, key2, &value2, sizeof(int), true);
app_message_outbox_send();
show_selected_title_and_mode();
}
// When looking at an option, do this when the up button is clicked
static void up_click_handler(ClickRecognizerRef recognizer, void *context) {
s_current_option--;
if (s_current_option < 0) {
s_current_option = NUM_ROWS - 1;
}
MenuIndex idx = menu_layer_get_selected_index(s_menu_layer);
idx.row = s_current_option;
menu_layer_set_selected_index(s_menu_layer, idx, MenuRowAlignCenter, false);
show_selected_title_and_mode();
}
// When looking at an option, do this when the down button is pressed
static void down_click_handler(ClickRecognizerRef recognizer, void *context) {
s_current_option++;
if ((unsigned)s_current_option >= NUM_ROWS) {
s_current_option = 0;
}
MenuIndex idx = menu_layer_get_selected_index(s_menu_layer);
idx.row = s_current_option;
menu_layer_set_selected_index(s_menu_layer, idx, MenuRowAlignCenter, false);
show_selected_title_and_mode();
}
// Configure clicking when in app
static void click_config_provider(void *context) {
window_single_click_subscribe(BUTTON_ID_SELECT, (ClickHandler)select_click_handler);
window_single_click_subscribe(BUTTON_ID_UP, (ClickHandler)up_click_handler);
window_single_click_subscribe(BUTTON_ID_DOWN, (ClickHandler)down_click_handler);
}
static void option_window_load(Window *window) {
// Define some event handlers for clicks
window_set_click_config_provider(window, (ClickConfigProvider) click_config_provider);
Layer *window_layer = window_get_root_layer(window);
GRect window_bounds = layer_get_bounds(window_layer);
// Arrange the three text layers on top of each other
window_bounds.size.h -= 40;
s_text_layer = text_layer_create(window_bounds);
s_title = text_layer_create(GRect(5, 38, 139, 50));
text_layer_set_background_color(s_title, GColorWhite);
text_layer_set_text_color(s_title, GColorBlack);
text_layer_set_font(s_title, fonts_get_system_font(FONT_KEY_DROID_SERIF_28_BOLD));
text_layer_set_text_alignment(s_title, GTextAlignmentCenter);
s_mode = text_layer_create(GRect(5, 74, 139, 96));
text_layer_set_background_color(s_mode, GColorWhite);
text_layer_set_text_color(s_mode, GColorBlack);
text_layer_set_font(s_mode, fonts_get_system_font(FONT_KEY_GOTHIC_24));
text_layer_set_text_alignment(s_mode, GTextAlignmentCenter);
// Add the child layer to the current window (s_option_window)
layer_add_child(window_layer, text_layer_get_layer(s_text_layer));
layer_add_child(window_layer, text_layer_get_layer(s_title));
layer_add_child(window_layer, text_layer_get_layer(s_mode));
// Update the text in the layers
show_selected_title_and_mode();
}
// Unload window
static void option_window_unload(Window *window) {
layer_remove_child_layers(window_get_root_layer(window));
text_layer_destroy(s_text_layer);
}
static void init() {
s_main_window = window_create();
window_set_window_handlers(s_main_window, (WindowHandlers) {
.load = main_window_load,
.unload = main_window_unload
});
s_option_window = window_create();
window_set_window_handlers(s_option_window, (WindowHandlers) {
.load = option_window_load,
.unload = option_window_unload
});
window_stack_push(s_main_window, true);
app_message_register_inbox_received(inbox_received_callback);
app_message_register_inbox_dropped(inbox_dropped_callback);
app_message_register_outbox_failed(outbox_failed_callback);
app_message_register_outbox_sent(outbox_sent_callback);
app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum());
}
static void deinit() {
window_destroy(s_option_window);
window_destroy(s_main_window);
}
int main(void) {
init();
app_event_loop();
deinit();
}
Comments