diff --git a/CMakeLists.txt b/CMakeLists.txt index a3ca8fb..e9cd15f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5) project(hello) SET(PEBBLE_FLAVOUR basalt) -SET(PEBBLE_SDK_VER 3.13.1) +SET(PEBBLE_SDK_VER 3.14) SET(PEBBLE_SDK "/opt/pebble-sdk") INCLUDE_DIRECTORIES("${PEBBLE_SDK}/.pebble-sdk/SDKs/${PEBBLE_SDK_VER}/sdk-core/pebble/${PEBBLE_FLAVOUR}/include") INCLUDE_DIRECTORIES("build/${PEBBLE_FLAVOUR}/src") @@ -22,6 +22,8 @@ set(SOURCE_FILES src/windows/action/action_window.h src/windows/action/style.h src/layers/border_layer.c - src/layers/border_layer.h) + src/layers/border_layer.h + src/windows/action/action_menu_layer.c + src/windows/action/action_menu_layer.h src/windows/list/list_layer.c src/windows/list/list_layer.h) add_executable(hello ${SOURCE_FILES}) \ No newline at end of file diff --git a/package.json b/package.json index 8884f5c..4c559e0 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,7 @@ "sdkVersion": "3", "enableMultiJS": true, "targetPlatforms": [ - "aplite", - "basalt", - "chalk" + "basalt" ], "watchapp": { "watchface": false @@ -25,26 +23,6 @@ ], "resources": { "media": [ - { - "type": "bitmap", - "name": "TICK_BLACK", - "file": "images/tick_black.png" - }, - { - "type": "bitmap", - "name": "TICK_WHITE", - "file": "images/tick_white.png" - }, - { - "type": "bitmap", - "name": "CROSS_WHITE", - "file": "images/cross_white.png" - }, - { - "type": "bitmap", - "name": "CROSS_BLACK", - "file": "images/cross_black.png" - } ] } } diff --git a/resources/images/cross_black.png b/resources/images/cross_black.png deleted file mode 100644 index bf16c86..0000000 Binary files a/resources/images/cross_black.png and /dev/null differ diff --git a/resources/images/cross_white.png b/resources/images/cross_white.png deleted file mode 100644 index bf16c86..0000000 Binary files a/resources/images/cross_white.png and /dev/null differ diff --git a/resources/images/tick_black.png b/resources/images/tick_black.png deleted file mode 100644 index 632b0ac..0000000 Binary files a/resources/images/tick_black.png and /dev/null differ diff --git a/resources/images/tick_white.png b/resources/images/tick_white.png deleted file mode 100644 index 7509013..0000000 Binary files a/resources/images/tick_white.png and /dev/null differ diff --git a/src/layers/border_layer.c b/src/layers/border_layer.c index b0577cf..e87f14e 100644 --- a/src/layers/border_layer.c +++ b/src/layers/border_layer.c @@ -26,6 +26,7 @@ struct BorderLayer* get_data(const struct Layer *layer) return border; } +// callback: LayerUpdateProc static void on_update(struct Layer *layer, GContext *context) { struct BorderLayer *border = get_data(layer); @@ -39,12 +40,12 @@ static void on_update(struct Layer *layer, GContext *context) graphics_fill_rect(context, rect, 0, GCornerNone); } -static struct Layer* create_layer(struct BorderLayer *border, - struct GRect frame) +static struct Layer* create_raw_layer(struct BorderLayer *border, + struct GRect frame) { size_t data_region_size = sizeof(struct BorderLayer *); struct Layer *layer = layer_create_with_data(frame, data_region_size); - layer_set_update_proc(layer, on_update); + if(!layer) return NULL; struct BorderLayer **data_region = layer_get_data(layer); *data_region = border; @@ -52,14 +53,36 @@ static struct Layer* create_layer(struct BorderLayer *border, return layer; } -void BORDER_LAYER_init(struct BorderLayer *border, struct GRect frame) +void BORDER_LAYER_add_to_layer(struct BorderLayer *border, + struct Layer *root_layer) { - border->raw_layer = create_layer(border, frame); - border->color = GColorWhite; - border->width = 5; + struct Layer *raw_layer = border->raw_layer; + layer_add_child(root_layer, raw_layer); +} + +struct BorderLayer *BORDER_LAYER_create(struct GRect frame) +{ + struct BorderLayer *border_layer = 0; + + border_layer = (struct BorderLayer*) malloc(sizeof(struct BorderLayer)); + if(!border_layer) return NULL; + + struct Layer *raw_layer = create_raw_layer(border_layer, frame); + if(!raw_layer) return NULL; + + layer_set_update_proc(raw_layer, on_update); + + border_layer->raw_layer = raw_layer; + border_layer->color = GColorWhite; + border_layer->width = 5; + + return border_layer; } void BORDER_LAYER_destroy(struct BorderLayer *border) { + if(!border) return; + layer_destroy(border->raw_layer); + free(border); } \ No newline at end of file diff --git a/src/layers/border_layer.h b/src/layers/border_layer.h index ca7e652..b56ab60 100644 --- a/src/layers/border_layer.h +++ b/src/layers/border_layer.h @@ -28,6 +28,9 @@ struct BorderLayer Layer *raw_layer; }; -void BORDER_LAYER_init(struct BorderLayer *border, struct GRect frame); +void BORDER_LAYER_add_to_layer(struct BorderLayer *border, + struct Layer *root_layer); + +struct BorderLayer *BORDER_LAYER_create(struct GRect frame); void BORDER_LAYER_destroy(struct BorderLayer *border); \ No newline at end of file diff --git a/src/main.c b/src/main.c index fbe73f0..cf7b19a 100644 --- a/src/main.c +++ b/src/main.c @@ -22,7 +22,10 @@ int main(void) { - LIST_WINDOW_push(); + struct ListWindow *window = LIST_WINDOW_create(); + window_stack_push(window->raw_window, true); + app_event_loop(); - LIST_WINDOW_destroy(); + + LIST_WINDOW_destroy(window); } diff --git a/src/network.c b/src/network.c index 6bdba97..9b54b63 100644 --- a/src/network.c +++ b/src/network.c @@ -20,7 +20,6 @@ #include #include "network.h" #include "util.h" -#include "windows/list/list_window.h" #define MAX_HABIT_COUNT 50 static int HABIT_COUNT; @@ -64,8 +63,8 @@ static int process_count(DictionaryIterator *iter) int count = tuple->value->int32; - rval = LIST_WINDOW_allocate(count); - abort_if(rval, "LIST_WINDOW_allocate failed"); +// rval = LIST_WINDOW_allocate(count); +// abort_if(rval, "LIST_WINDOW_allocate failed"); if(count > MAX_HABIT_COUNT) count = MAX_HABIT_COUNT; HABIT_COUNT = count; @@ -82,23 +81,23 @@ static int process_habit(DictionaryIterator *iter) { int rval = 0; - // id - Tuple *tuple = dict_find(iter, 1); - abort_if(!tuple, "tuple is null"); - int id = tuple->value->int32; - - // name - tuple = dict_find(iter, 2); - abort_if(!tuple, "tuple is null"); - char *name = tuple->value->cstring; - - // checkmark value - tuple = dict_find(iter, 3); - abort_if(!tuple, "tuple is null"); - int checkmark = tuple->value->int32; - - rval = LIST_WINDOW_add_habit(id, name, checkmark); - abort_if(rval, "LIST_WINDOW_add_habit failed"); +// // id +// Tuple *tuple = dict_find(iter, 1); +// abort_if(!tuple, "tuple is null"); +// int id = tuple->value->int32; +// +// // name +// tuple = dict_find(iter, 2); +// abort_if(!tuple, "tuple is null"); +// char *name = tuple->value->cstring; +// +// // checkmark value +// tuple = dict_find(iter, 3); +// abort_if(!tuple, "tuple is null"); +// int checkmark = tuple->value->int32; + +// rval = LIST_WINDOW_add_habit(id, name, checkmark); +// abort_if(rval, "LIST_WINDOW_add_habit failed"); rval = request_next_habit(); abort_if(rval, "request_next_habit failed"); diff --git a/src/windows/action/action_menu_layer.c b/src/windows/action/action_menu_layer.c new file mode 100644 index 0000000..f99ef5b --- /dev/null +++ b/src/windows/action/action_menu_layer.c @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include +#include "action_menu_layer.h" +#include "style.h" + +const char *ACTIONS[] = { + " Check", + " View stats" +}; + +// callback: MenuLayerSelectCallback +static void on_click(struct MenuLayer *menu_layer, + MenuIndex *cell_index, + void *callback_context) +{ + struct ActionMenuLayer *action_menu = callback_context; + if(!action_menu->callbacks.on_select) return; + action_menu->callbacks.on_select(action_menu->callback_context); +} + +// MenuLayerGetNumberOfRowsInSectionsCallback +static uint16_t on_get_num_rows(MenuLayer *menu_layer, + uint16_t section_index, + void *context) +{ + return 2; +} + +// MenuLayerDrawRowCallback +static void on_draw_row(GContext *ctx, + const Layer *cell_layer, + MenuIndex *cell_index, + void *extra) +{ + int n = cell_index->row; + menu_cell_basic_draw(ctx, cell_layer, ACTIONS[n], NULL, NULL); +} + +// MenuLayerGetCellHeightCallback +static int16_t on_get_cell_height(struct MenuLayer *menu_layer, + MenuIndex *cell_index, + void *context) +{ + return CELL_HEIGHT; +} + +static void set_menu_layer_callbacks(struct ActionMenuLayer *action_menu, + struct MenuLayer *menu) +{ + MenuLayerCallbacks callbacks = { + .get_num_rows = on_get_num_rows, + .draw_row = on_draw_row, + .get_cell_height = on_get_cell_height, + .select_click = on_click, + }; + + menu_layer_set_callbacks(menu, action_menu, callbacks); + menu_layer_set_highlight_colors(menu, HIGHLIGHT_BACKGROUND_COLOR, + HIGHLIGHT_FOREGROUND_COLOR); + menu_layer_set_normal_colors(menu, NORMAL_BACKGROUND_COLOR, + NORMAL_FOREGROUND_COLOR); +} + +void ACTION_MENU_LAYER_add_to_layer(struct ActionMenuLayer *action_menu, + struct Layer *root_layer) +{ + struct Layer *raw_layer = menu_layer_get_layer(action_menu->menu_layer); + layer_add_child(root_layer, raw_layer); +} + +void ACTION_MENU_LAYER_attach_to_window(struct ActionMenuLayer *action_menu, + struct Window *window) +{ + struct MenuLayer *menu = action_menu->menu_layer; + menu_layer_set_click_config_onto_window(menu, window); +}; + +struct ActionMenuLayer* ACTION_MENU_LAYER_create(struct GRect bounds) +{ + struct ActionMenuLayer *action_menu = 0; + action_menu = (struct ActionMenuLayer*) malloc(sizeof(struct ActionMenuLayer)); + if(!action_menu) return NULL; + + struct MenuLayer *menu = menu_layer_create(bounds); + if(!menu) return NULL; + + set_menu_layer_callbacks(action_menu, menu); + action_menu->menu_layer = menu; + + return action_menu; +} + +void ACTION_MENU_LAYER_destroy(struct ActionMenuLayer *action_menu) +{ + if(!action_menu) return; + if(action_menu->menu_layer) menu_layer_destroy(action_menu->menu_layer); + free(action_menu); +} \ No newline at end of file diff --git a/src/windows/action/action_menu_layer.h b/src/windows/action/action_menu_layer.h new file mode 100644 index 0000000..c9b76e1 --- /dev/null +++ b/src/windows/action/action_menu_layer.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#pragma once + +struct ActionMenuLayerCallbacks +{ + void (*on_select)(void *callback_context); +}; + +struct ActionMenuLayer +{ + struct MenuLayer *menu_layer; + + void *callback_context; + struct ActionMenuLayerCallbacks callbacks; +}; + +void ACTION_MENU_LAYER_attach_to_window(struct ActionMenuLayer *action_menu, + struct Window *window); + +void ACTION_MENU_LAYER_add_to_layer(struct ActionMenuLayer *action_menu, + struct Layer *root_layer); + +void ACTION_MENU_LAYER_destroy(struct ActionMenuLayer *action_menu); + +struct ActionMenuLayer* ACTION_MENU_LAYER_create(struct GRect bounds); diff --git a/src/windows/action/action_window.c b/src/windows/action/action_window.c index e0d2626..b4a5a0d 100644 --- a/src/windows/action/action_window.c +++ b/src/windows/action/action_window.c @@ -19,128 +19,108 @@ #include #include "action_window.h" -#include "style.h" #include "../../layers/border_layer.h" #include "../../util.h" +#include "action_menu_layer.h" +#include "style.h" -static struct Window *WINDOW = 0; -static struct MenuLayer *MENU_LAYER = 0; -static struct BorderLayer *BORDER_LAYER = 0; - -char *ACTIONS[] = { " Check", " View stats"}; - -// DRAWING -//------------------------------------------------------------------------------ - -void draw_left_border(GContext *ctx, const Layer *cell_layer) -{ - GRect bounds = layer_get_bounds(cell_layer); - GRect rect = GRect(bounds.origin.x, bounds.origin.y, 5, bounds.size.h); - graphics_context_set_fill_color(ctx, GColorFolly); - graphics_fill_rect(ctx, rect, 0, GCornerNone); -} - -// MENU LAYER CALLBACKS -//------------------------------------------------------------------------------ - -static uint16_t get_num_rows(MenuLayer *menu_layer, - uint16_t section_index, - void *context) +static void on_select(void *callback_context) { - return 2; + window_stack_pop(true); } -static void draw_row(GContext *ctx, - const Layer *cell_layer, - MenuIndex *cell_index, - void *extra) +static int add_menu_layer(struct ActionWindow *window, + struct Layer *root_layer, + struct GRect bounds) { - int n = cell_index->row; - menu_cell_basic_draw(ctx, cell_layer, ACTIONS[n], NULL, NULL); - draw_left_border(ctx, cell_layer); -} + int rval = 0; -static int16_t get_cell_height(struct MenuLayer *menu_layer, - MenuIndex *cell_index, - void *context) -{ - return CELL_HEIGHT; -} + struct ActionMenuLayer *menu_layer = 0; + menu_layer = ACTION_MENU_LAYER_create(bounds); + abort_if(!menu_layer, "ACTION_MENU_LAYER_create failed"); -static void select_click(MenuLayer *menu_layer, MenuIndex *index, void *context) -{ -} + window->menu_layer = menu_layer; + ACTION_MENU_LAYER_attach_to_window(menu_layer, window->raw_window); + ACTION_MENU_LAYER_add_to_layer(menu_layer, root_layer); -// WINDOWS HANDLERS -//------------------------------------------------------------------------------ - -void add_menu_layer(Window *window, - Layer *root_layer, - GRect bounds) -{ - MenuLayerCallbacks callbacks = { - .get_num_rows = get_num_rows, - .draw_row = draw_row, - .get_cell_height = get_cell_height, - .select_click = select_click, + menu_layer->callback_context = window; + menu_layer->callbacks = (struct ActionMenuLayerCallbacks) { + .on_select = on_select }; - MENU_LAYER = menu_layer_create(bounds); - menu_layer_set_click_config_onto_window(MENU_LAYER, window); - menu_layer_set_callbacks(MENU_LAYER, NULL, callbacks); - menu_layer_set_highlight_colors(MENU_LAYER, HIGHLIGHT_BACKGROUND_COLOR, - HIGHLIGHT_FOREGROUND_COLOR); - menu_layer_set_normal_colors(MENU_LAYER, NORMAL_BACKGROUND_COLOR, - NORMAL_FOREGROUND_COLOR); - - layer_add_child(root_layer, menu_layer_get_layer(MENU_LAYER)); +CLEANUP: + return rval; } -static int add_border_layer(Window *window, Layer *root_layer, GRect frame) +static int add_border_layer(struct ActionWindow *window, + struct Layer *root_layer, + const struct GRect frame) { int rval = 0; - BORDER_LAYER = (struct BorderLayer*) malloc(sizeof(struct BorderLayer)); - abort_if(!BORDER_LAYER, "could not allocate BORDER_LAYER"); + struct BorderLayer *border_layer = 0; + + border_layer = BORDER_LAYER_create(frame); + abort_if(!border_layer, "BORDER_LAYER_create failed"); - BORDER_LAYER_init(BORDER_LAYER, frame); - BORDER_LAYER->color = GColorFolly; + border_layer->color = BORDER_COLOR; + border_layer->width = BORDER_WIDTH; - layer_add_child(root_layer, BORDER_LAYER->raw_layer); + window->border_layer = border_layer; + BORDER_LAYER_add_to_layer(border_layer, root_layer); CLEANUP: return rval; } -static void on_load(Window *window) +// callback: WindowHandler +static void on_load(Window *raw_window) { - Layer *root_layer = window_get_root_layer(window); + struct ActionWindow *window = window_get_user_data(raw_window); + Layer *root_layer = window_get_root_layer(raw_window); GRect bounds = layer_get_bounds(root_layer); add_menu_layer(window, root_layer, bounds); add_border_layer(window, root_layer, bounds); } -static void on_unload(Window *window) +// callback: WindowHandler +static void on_unload(Window *raw_window) { - menu_layer_destroy(MENU_LAYER); - free(BORDER_LAYER); + struct ActionWindow *window = window_get_user_data(raw_window); + ACTION_MENU_LAYER_destroy(window->menu_layer); + BORDER_LAYER_destroy(window->border_layer); } -//-------------------------------------------------------------------------------- - -void ACTION_WINDOW_push() +static void set_raw_window_handlers(Window *raw_window) { WindowHandlers handlers = { - .load = on_load, - .unload = on_unload + .load = on_load, + .unload = on_unload }; - WINDOW = window_create(); - window_set_window_handlers(WINDOW, handlers); - window_stack_push(WINDOW, true); + window_set_window_handlers(raw_window, handlers); +} + +struct ActionWindow *ACTION_WINDOW_create() +{ + struct ActionWindow *window = 0; + + window = (struct ActionWindow*) malloc(sizeof(struct ActionWindow)); + if(!window) return NULL; + + Window *raw_window = window_create(); + if(!raw_window) return NULL; + + window->raw_window = raw_window; + window_set_user_data(raw_window, window); + set_raw_window_handlers(raw_window); + + return window; } -void ACTION_WINDOW_destroy() +void ACTION_WINDOW_destroy(struct ActionWindow *window) { - window_destroy(WINDOW); + if(!window) return; + window_destroy(window->raw_window); + free(window); } \ No newline at end of file diff --git a/src/windows/action/action_window.h b/src/windows/action/action_window.h index e2394be..766ad5c 100644 --- a/src/windows/action/action_window.h +++ b/src/windows/action/action_window.h @@ -19,6 +19,15 @@ #pragma once -void ACTION_WINDOW_push(); +struct ActionWindow +{ + struct Window *raw_window; -void ACTION_WINDOW_destroy(); \ No newline at end of file + struct ActionMenuLayer *menu_layer; + + struct BorderLayer *border_layer; +}; + +struct ActionWindow* ACTION_WINDOW_create(); + +void ACTION_WINDOW_destroy(struct ActionWindow *window); \ No newline at end of file diff --git a/src/windows/action/style.h b/src/windows/action/style.h index d133036..a4644fb 100644 --- a/src/windows/action/style.h +++ b/src/windows/action/style.h @@ -29,4 +29,8 @@ #define NORMAL_FOREGROUND_COLOR GColorDarkGray +#define BORDER_COLOR GColorFolly + +#define BORDER_WIDTH 10 + #define CELL_HEIGHT 36 \ No newline at end of file diff --git a/src/windows/list/list_layer.c b/src/windows/list/list_layer.c new file mode 100644 index 0000000..46b1994 --- /dev/null +++ b/src/windows/list/list_layer.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "list_layer.h" +#include "style.h" +#include "../../util.h" + +#define MAX_NAME_LENGTH 20 + +static int free_habits(struct ListLayer *layer) +{ + for(int i = 0; i < layer->habit_count; i++) free(layer->habit_names[i]); + free(layer->habit_names); + free(layer->habit_checkmarks); + free(layer->habit_ids); + layer->habit_count = 0; + + return 0; +} + +int LIST_LAYER_allocate(struct ListLayer *layer, int count) +{ + int rval = 0; + + free_habits(layer); + + layer->habit_names = (char **) malloc(count * sizeof(char *)); + abort_if(!layer->habit_names, "could not allocate habit_names"); + + for(int i = 0; i < count; i++) + { + layer->habit_names[i] = (char *) malloc(MAX_NAME_LENGTH * sizeof(char)); + abort_if(!layer->habit_names[i], "could not allocate habit_names"); + } + + layer->habit_checkmarks = (int *) malloc(count * sizeof(int)); + abort_if(!layer->habit_checkmarks, "could not allocate habit_checkmarks"); + + layer->habit_ids = (int *) malloc(count * sizeof(int)); + abort_if(!layer->habit_ids, "could not allocate habit_ids"); + +CLEANUP: + return rval; +} + +int LIST_LAYER_add_habit(struct ListLayer *layer, + int new_id, + char *new_name, + int new_checkmark) +{ + uint16_t count = layer->habit_count; + + char *name = layer->habit_names[count]; + strncpy(name, new_name, MAX_NAME_LENGTH); + menu_layer_reload_data(layer->menu_layer); + + layer->habit_ids[count] = new_id; + layer->habit_checkmarks[count] = new_checkmark; + layer->habit_count++; + + return 0; +} + +static uint16_t get_num_rows(MenuLayer *menu_layer, + uint16_t section_index, + void *callback_context) +{ + struct ListLayer *list_layer = callback_context; + return list_layer->habit_count; +} + +static void on_draw_row(GContext *ctx, + const Layer *cell_layer, + MenuIndex *cell_index, + void *callback_context) +{ + int n = cell_index->row; + struct ListLayer *list_layer = callback_context; + char *name = list_layer->habit_names[n]; + + menu_cell_basic_draw(ctx, cell_layer, name, NULL, NULL); +} + +static int16_t get_cell_height(struct MenuLayer *menu_layer, + MenuIndex *cell_index, + void *callback_context) +{ + return CELL_HEIGHT; +} + +static void select_click(struct MenuLayer *menu_layer, + struct MenuIndex *index, + void *callback_context) +{ + struct ListLayer *list_layer = callback_context; + if(!list_layer->callbacks.on_select) return; + + list_layer->callbacks.on_select(list_layer->callback_context); +} + +static void request_list(void *context) +{ + struct ListLayer *layer = context; + + LIST_LAYER_allocate(layer, 4); + LIST_LAYER_add_habit(layer, 0, "Wake up early", 0); + LIST_LAYER_add_habit(layer, 1, "Meditate", 1); + LIST_LAYER_add_habit(layer, 2, "Exercise", 1); + LIST_LAYER_add_habit(layer, 3, "Go to school", 0); +} + +static void set_menu_layer_callbacks(struct ListLayer *list_layer, + MenuLayer *menu_layer) +{ + MenuLayerCallbacks callbacks = { + .get_num_rows = get_num_rows, + .draw_row = on_draw_row, + .get_cell_height = get_cell_height, + .select_click = select_click, + }; + + menu_layer_set_callbacks(menu_layer, list_layer, callbacks); +} + +static void set_menu_layer_styles(MenuLayer *menu_layer) +{ + menu_layer_set_highlight_colors(menu_layer, HIGHLIGHT_BACKGROUND_COLOR, + HIGHLIGHT_FOREGROUND_COLOR); + menu_layer_set_normal_colors(menu_layer, NORMAL_BACKGROUND_COLOR, + NORMAL_FOREGROUND_COLOR); +} + +void LIST_LAYER_attach_to_window(struct ListLayer *layer, struct Window *window) +{ + menu_layer_set_click_config_onto_window(layer->menu_layer, window); + app_timer_register(500, request_list, layer); +} + +void LIST_LAYER_add_to_layer(struct ListLayer *layer, struct Layer *root_layer) +{ + struct Layer *raw_layer = menu_layer_get_layer(layer->menu_layer); + layer_add_child(root_layer, raw_layer); +} + +struct ListLayer* LIST_LAYER_create(struct GRect bounds) +{ + struct ListLayer *list_layer = 0; + list_layer = (struct ListLayer*) malloc(sizeof(struct ListLayer)); + if(!list_layer) return NULL; + + MenuLayer *menu_layer = menu_layer_create(bounds); + if(!menu_layer) return NULL; + set_menu_layer_styles(menu_layer); + set_menu_layer_callbacks(list_layer, menu_layer); + list_layer->menu_layer = menu_layer; + + list_layer->habit_count = 0; + + return list_layer; +} + +void LIST_LAYER_destroy(struct ListLayer *list_layer) +{ + if(!list_layer) return; + free_habits(list_layer); + menu_layer_destroy(list_layer->menu_layer); + free(list_layer); +} \ No newline at end of file diff --git a/src/windows/list/list_layer.h b/src/windows/list/list_layer.h new file mode 100644 index 0000000..997abdf --- /dev/null +++ b/src/windows/list/list_layer.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ +#pragma once + +#include + +struct ListLayerCallbacks +{ + void (*on_select)(void *callback_context); +}; + +struct ListLayer +{ + uint16_t habit_count; + char **habit_names; + int *habit_ids; + int *habit_checkmarks; + + struct MenuLayer *menu_layer; + struct ActionWindow *action_window; + + void *callback_context; + struct ListLayerCallbacks callbacks; +}; + +void LIST_LAYER_attach_to_window(struct ListLayer *layer, struct Window *window); + +void LIST_LAYER_add_to_layer(struct ListLayer *layer, struct Layer *root_layer); + +struct ListLayer* LIST_LAYER_create(struct GRect bounds); + +void LIST_LAYER_destroy(struct ListLayer *layer); \ No newline at end of file diff --git a/src/windows/list/list_window.c b/src/windows/list/list_window.c index 4fd30da..f1697e6 100644 --- a/src/windows/list/list_window.c +++ b/src/windows/list/list_window.c @@ -18,212 +18,73 @@ */ #include -#include "../../network.h" -#include "../../util.h" #include "list_window.h" #include "../action/action_window.h" -#include "style.h" +#include "list_layer.h" -static Window *WINDOW = 0; -static MenuLayer *MENU_LAYER = 0; - -static uint16_t HABIT_COUNT = 0; -static char **HABIT_NAMES = 0; -static int *HABIT_IDS = 0; -static int *HABIT_CHECKMARKS = 0; -static size_t MAX_NAME_LENGTH = 20; - -static GBitmap *TICK_WHITE; -static GBitmap *TICK_BLACK; -static GBitmap *CROSS_BLACK; -static GBitmap *CROSS_WHITE; - -int LIST_WINDOW_allocate(int count); - -int LIST_WINDOW_add_habit(int new_id, char *new_name, int new_checkmark); - -void free_habits() -{ - HABIT_COUNT = 0; - for (int i = 0; i < HABIT_COUNT; i++) free(HABIT_NAMES[i]); - free(HABIT_NAMES); - free(HABIT_IDS); -} - -// MENU LAYER CALLBACKS -//------------------------------------------------------------------------------ - -static uint16_t get_num_rows(MenuLayer *menu_layer, - uint16_t section_index, - void *context) -{ - return HABIT_COUNT; -} - -GBitmap *getTickBitmap(int highlighted) -{ - return highlighted ? TICK_WHITE : TICK_BLACK; -} - -GBitmap *getCrossBitmap(int highlighted) +static void on_select(void *callback_context) { - return highlighted ? CROSS_WHITE : CROSS_BLACK; -} - -GBitmap *getIcon(int is_checked, int is_highlighted) -{ - if(is_checked == 0) return getCrossBitmap(is_highlighted); - else return getTickBitmap(is_highlighted); -} - -static void draw_row(GContext *ctx, - const Layer *cell_layer, - MenuIndex *cell_index, - void *context) -{ - int n = cell_index->row; - char *name = HABIT_NAMES[n]; - int is_checked = HABIT_CHECKMARKS[n]; - int is_highlighted = menu_cell_layer_is_highlighted(cell_layer); - - GBitmap *icon = getIcon(is_checked, is_highlighted); - menu_cell_basic_draw(ctx, cell_layer, name, NULL, NULL); -} - -static int16_t get_cell_height(struct MenuLayer *menu_layer, - MenuIndex *cell_index, - void *context) -{ - return CELL_HEIGHT; -} - -static void select_click(MenuLayer *menu_layer, MenuIndex *index, void *context) -{ - int n = index->row; - int id = HABIT_IDS[n]; -// NETWORK_request_toggle(id); - - ACTION_WINDOW_push(); + struct ListWindow *window = callback_context; + LIST_WINDOW_show_action_window(window); } -static void request_list(void *context) +// callback: WindowHandler +static void on_load(Window *raw_window) { - LIST_WINDOW_allocate(5); - LIST_WINDOW_add_habit(0, "Wake up early", 0); - LIST_WINDOW_add_habit(1, "Meditate", 1); - LIST_WINDOW_add_habit(2, "Exercise", 1); - LIST_WINDOW_add_habit(3, "Go to school", 0); - - NETWORK_request_list(); -} - -// WINDOWS HANDLERS -//------------------------------------------------------------------------------ - -static void on_load(Window *window) -{ - Layer *root_layer = window_get_root_layer(window); + Layer *root_layer = window_get_root_layer(raw_window); GRect bounds = layer_get_bounds(root_layer); + struct ListWindow *window = window_get_user_data(raw_window); - MenuLayerCallbacks callbacks = { - .get_num_rows = get_num_rows, - .draw_row = draw_row, - .get_cell_height = get_cell_height, - .select_click = select_click, - }; - - MENU_LAYER = menu_layer_create(bounds); - menu_layer_set_click_config_onto_window(MENU_LAYER, window); - menu_layer_set_callbacks(MENU_LAYER, NULL, callbacks); - menu_layer_set_highlight_colors(MENU_LAYER, HIGHLIGHT_BACKGROUND_COLOR, - HIGHLIGHT_FOREGROUND_COLOR); - menu_layer_set_normal_colors(MENU_LAYER, NORMAL_BACKGROUND_COLOR, - NORMAL_FOREGROUND_COLOR); + window->list_layer = LIST_LAYER_create(bounds); + LIST_LAYER_attach_to_window(window->list_layer, raw_window); + LIST_LAYER_add_to_layer(window->list_layer, root_layer); - layer_add_child(root_layer, menu_layer_get_layer(MENU_LAYER)); - app_timer_register(500, request_list, 0); + window->list_layer->callback_context = window; + window->list_layer->callbacks = (struct ListLayerCallbacks) { + .on_select = on_select + }; } -static void on_unload(Window *window) +// callback: WindowHandler +static void on_unload(Window *raw_window) { - menu_layer_destroy(MENU_LAYER); -} - -//-------------------------------------------------------------------------------- - -int LIST_WINDOW_allocate(int count) -{ - int rval = 0; - - if(HABIT_COUNT > 0) free_habits(); - - HABIT_NAMES = (char**) malloc(count * sizeof(char*)); - abort_if(!HABIT_NAMES, "could not allocate HABIT_NAMES"); - - for(int i = 0; i < count; i++) - { - HABIT_NAMES[i] = (char*) malloc(MAX_NAME_LENGTH * sizeof(char)); - abort_iff(!HABIT_NAMES[i], "could not allocate HABIT_NAMES[%d]", i); - } - - HABIT_CHECKMARKS = (int *) malloc(count * sizeof(int)); - abort_if(!HABIT_CHECKMARKS, "could not allocate HABIT_CHECKMARKS"); - - HABIT_IDS = (int *) malloc(count * sizeof(int)); - abort_if(!HABIT_IDS, "could not allocate HABIT_IDS"); - -CLEANUP: - return rval; + struct ListWindow *list_window = window_get_user_data(raw_window); + LIST_LAYER_destroy(list_window->list_layer); + ACTION_WINDOW_destroy(list_window->action_window); } -int LIST_WINDOW_add_habit(int new_id, char *new_name, int new_checkmark) +void LIST_WINDOW_show_action_window(struct ListWindow *window) { - char *name = HABIT_NAMES[HABIT_COUNT]; - strncpy(name, new_name, MAX_NAME_LENGTH); - menu_layer_reload_data(MENU_LAYER); - - HABIT_IDS[HABIT_COUNT] = new_id; - HABIT_CHECKMARKS[HABIT_COUNT] = new_checkmark; - HABIT_COUNT++; - - return 0; -} + ACTION_WINDOW_destroy(window->action_window); -void create_bitmaps() -{ - CROSS_BLACK = gbitmap_create_with_resource(RESOURCE_ID_CROSS_BLACK); - CROSS_WHITE = gbitmap_create_with_resource(RESOURCE_ID_CROSS_WHITE); - TICK_WHITE = gbitmap_create_with_resource(RESOURCE_ID_TICK_WHITE); - TICK_BLACK = gbitmap_create_with_resource(RESOURCE_ID_TICK_BLACK); -} + window->action_window = ACTION_WINDOW_create(); + if(!window->action_window) return; -void free_bitmaps() -{ - gbitmap_destroy(CROSS_BLACK); - gbitmap_destroy(CROSS_WHITE); - gbitmap_destroy(TICK_WHITE); - gbitmap_destroy(TICK_BLACK); + window_stack_push(window->action_window->raw_window, true); } -void LIST_WINDOW_push() +struct ListWindow *LIST_WINDOW_create() { - NETWORK_register(); - - create_bitmaps(); - WindowHandlers handlers = { .load = on_load, .unload = on_unload }; - WINDOW = window_create(); - window_set_window_handlers(WINDOW, handlers); - window_stack_push(WINDOW, true); + struct ListWindow *list_window = 0; + list_window = (struct ListWindow*) malloc(sizeof(struct ListWindow)); + if(!list_window) return NULL; + + Window *raw_window = window_create(); + window_set_user_data(raw_window, list_window); + window_set_window_handlers(raw_window, handlers); + list_window->raw_window = raw_window; + + return list_window; } -void LIST_WINDOW_destroy() +void LIST_WINDOW_destroy(struct ListWindow *list_window) { - free_bitmaps(); - free_habits(); - window_destroy(WINDOW); + if(!list_window) return; + window_destroy(list_window->raw_window); + free(list_window); } \ No newline at end of file diff --git a/src/windows/list/list_window.h b/src/windows/list/list_window.h index da535e9..41b766d 100644 --- a/src/windows/list/list_window.h +++ b/src/windows/list/list_window.h @@ -19,10 +19,15 @@ #pragma once -void LIST_WINDOW_push(); +struct ListWindow +{ + struct Window *raw_window; + struct ListLayer *list_layer; + struct ActionWindow *action_window; +}; -void LIST_WINDOW_destroy(); +void LIST_WINDOW_show_action_window(struct ListWindow *window); -int LIST_WINDOW_allocate(int count); +struct ListWindow *LIST_WINDOW_create(); -int LIST_WINDOW_add_habit(int new_id, char *new_checkmark, int i); +void LIST_WINDOW_destroy(struct ListWindow *window);