#include #include "scrolllayer.h" #include "src/c/colors.h" #include "src/c/settings.h" static ScrollLayer *s_scroll_layer; static Layer *s_scroll_bar_layer; static GFont s_scrolllayer_font; static GFont s_scrolllayer_font_small; static GBitmap *s_background_bitmap; static GBitmap *s_plus_bitmap; static GBitmap *s_minus_bitmap; static GBitmap *s_background_plus_pressed_bitmap; static GBitmap *s_background_minus_pressed_bitmap; static GBitmap *s_scroll_bar_current_bitmap; static GBitmap *s_scroll_bar_full_bitmap; static GBitmap *s_scroll_bar_half_bitmap; static GBitmap *s_scroll_bar_third_bitmap; // TOUCH BUTTONS static GRect item_1_plus_button; static GRect item_1_minus_button; static GRect item_2_plus_button; static GRect item_2_minus_button; static GRect item_3_plus_button; static GRect item_3_minus_button; // SCROLL static int s_scroll_y; static int s_scroll_page; static scroll_items_t s_scroll_items; // SETTINGS settings_t *app_settings; // ------------ SCROLL ------------ static void scroll_up(ClickRecognizerRef recognizer, void *context) { s_scroll_y -= MAX_UI_ITEMS * ITEM_UI_HEIGHT; s_scroll_page -= 1; if (s_scroll_y < 0) { s_scroll_y = 0; } if (s_scroll_page < 0) { s_scroll_page = 0; } // Move scroll bar GRect scroll_frame = layer_get_frame(s_scroll_bar_layer); int scroll_frame_y = scroll_frame.origin.y - scroll_frame.size.h; if (scroll_frame_y < SCROLL_BAR_ORIGIN_HEIGHT) { scroll_frame_y = SCROLL_BAR_ORIGIN_HEIGHT; } scroll_frame.origin.y = scroll_frame_y; layer_set_frame(s_scroll_bar_layer, scroll_frame); layer_mark_dirty(s_scroll_bar_layer); scroll_layer_set_content_offset( s_scroll_layer, GPoint(0, -s_scroll_y), true ); } static void scroll_down(ClickRecognizerRef recognizer, void *context) { s_scroll_y += MAX_UI_ITEMS * ITEM_UI_HEIGHT; s_scroll_page += 1; int max_scroll = MAX_UI_ITEMS * ITEM_UI_HEIGHT * (s_scroll_items.page_count - 1); if (s_scroll_y > max_scroll) { s_scroll_y = max_scroll; } if (s_scroll_page > ((MAX_ITEMS / MAX_UI_ITEMS) - 1)) { s_scroll_page = ((MAX_ITEMS / MAX_UI_ITEMS) - 1); } // Move scroll bar GRect scroll_frame = layer_get_frame(s_scroll_bar_layer); int scroll_frame_y = scroll_frame.origin.y + scroll_frame.size.h; if (scroll_frame_y > (SCROLL_BAR_ORIGIN_HEIGHT_END - scroll_frame.size.h)) { scroll_frame_y = (SCROLL_BAR_ORIGIN_HEIGHT_END - scroll_frame.size.h); } scroll_frame.origin.y = scroll_frame_y; layer_set_frame(s_scroll_bar_layer, scroll_frame); layer_mark_dirty(s_scroll_bar_layer); scroll_layer_set_content_offset( s_scroll_layer, GPoint(0, -s_scroll_y), true ); } // ------------ BUTTONS ------------ static void click_config_provider(void *context) { window_single_click_subscribe(BUTTON_ID_UP, scroll_up); window_single_click_subscribe(BUTTON_ID_DOWN, scroll_down); } // ------------ HELPERS ------------ static GColor get_color_float(float val) { GColor color; int percentage = (int)(val * 100.0); if (percentage < app_settings->red_limit) { color = RED; } else if (percentage < app_settings->orange_limit) { color = ORANGE; } else { color = GREEN; } return color; } static void bar_draw(Layer *layer, GContext *ctx) { GColor *color = layer_get_data(layer); graphics_context_set_fill_color(ctx, *color); graphics_fill_rect(ctx, layer_get_bounds(layer), 0, GCornerNone); } static void scroll_bar_draw(Layer *layer, GContext *ctx) { GRect bounds = gbitmap_get_bounds(s_scroll_bar_current_bitmap); graphics_draw_bitmap_in_rect(ctx, s_scroll_bar_current_bitmap, GRect(0, 0, bounds.size.w, bounds.size.h)); } static void fill_percentage_buffer(scroll_items_t *items, int element, int total, float percentage) { if (total > 1000) { items->items->items[element].show_percentage = true; } if (items->items->items[element].show_percentage) { int percentage_int = (percentage * 100); snprintf( items->numbers_buffer[element], sizeof(items->numbers_buffer[element]), "%d%%", percentage_int ); } else { snprintf( items->numbers_buffer[element], sizeof(items->numbers_buffer[element]), "%d/%d", items->items->items[element].successes, total ); } } void scroll_layer_add_items() { GRect bounds = SCROLLLAYER_FRAME_RECT; int n_items = s_scroll_items.items->num_items-1; if (n_items < 0) { n_items = 0; } s_scroll_items.page_count = (n_items / MAX_UI_ITEMS) + 1; // Add entries for (int i = 0; i < s_scroll_items.items->num_items; i++) { // Add background s_scroll_items.backgrounds[i] = bitmap_layer_create(GRect(0, i * ITEM_UI_HEIGHT, bounds.size.w, ITEM_UI_HEIGHT)); bitmap_layer_set_bitmap(s_scroll_items.backgrounds[i], s_background_bitmap); bitmap_layer_set_compositing_mode(s_scroll_items.backgrounds[i], GCompOpSet); // Set transparency scroll_layer_add_child(s_scroll_layer, bitmap_layer_get_layer(s_scroll_items.backgrounds[i])); // Add text int name_len = (int)strlen(s_scroll_items.items->items[i].name); s_scroll_items.texts[i] = text_layer_create(GRect(26, (i * ITEM_UI_HEIGHT) + 4, 124, 16)); text_layer_set_text(s_scroll_items.texts[i], s_scroll_items.items->items[i].name); if (name_len < 10) { text_layer_set_font(s_scroll_items.texts[i], s_scrolllayer_font); } else { text_layer_set_font(s_scroll_items.texts[i], s_scrolllayer_font_small); } text_layer_set_text_alignment(s_scroll_items.texts[i], GTextAlignmentCenter); text_layer_set_background_color(s_scroll_items.texts[i], GColorClear); text_layer_set_text_color(s_scroll_items.texts[i], WHITE); scroll_layer_add_child(s_scroll_layer, text_layer_get_layer(s_scroll_items.texts[i])); // Add percentage int total = s_scroll_items.items->items[i].successes + s_scroll_items.items->items[i].fails; float percentage = (float)s_scroll_items.items->items[i].successes / total; GColor color = get_color_float(percentage); s_scroll_items.numbers[i] = text_layer_create(GRect(26, (i * ITEM_UI_HEIGHT) + 18, 124, 16)); fill_percentage_buffer(&s_scroll_items, i, total, percentage); text_layer_set_text(s_scroll_items.numbers[i], s_scroll_items.numbers_buffer[i]); text_layer_set_font(s_scroll_items.numbers[i], s_scrolllayer_font); text_layer_set_text_alignment(s_scroll_items.numbers[i], GTextAlignmentCenter); text_layer_set_background_color(s_scroll_items.numbers[i], GColorClear); text_layer_set_text_color(s_scroll_items.numbers[i], color); scroll_layer_add_child(s_scroll_layer, text_layer_get_layer(s_scroll_items.numbers[i])); // Add plus button s_scroll_items.plus_buttons[i] = bitmap_layer_create(GRect(146, (i * ITEM_UI_HEIGHT) + 18, 20, 20)); bitmap_layer_set_bitmap(s_scroll_items.plus_buttons[i], s_plus_bitmap); bitmap_layer_set_compositing_mode(s_scroll_items.plus_buttons[i], GCompOpSet); // Set transparency scroll_layer_add_child(s_scroll_layer, bitmap_layer_get_layer(s_scroll_items.plus_buttons[i])); // Add minus button s_scroll_items.minus_buttons[i] = bitmap_layer_create(GRect(7, (i * ITEM_UI_HEIGHT) + 18, 20, 20)); bitmap_layer_set_bitmap(s_scroll_items.minus_buttons[i], s_minus_bitmap); bitmap_layer_set_compositing_mode(s_scroll_items.minus_buttons[i], GCompOpSet); // Set transparency scroll_layer_add_child(s_scroll_layer, bitmap_layer_get_layer(s_scroll_items.minus_buttons[i])); // Add bar int width = (PERCENTAGE_BAR_WIDTH) * percentage; GRect bar = GRect(31, (i * ITEM_UI_HEIGHT) + 40, width, 4); s_scroll_items.success_bars[i] = layer_create_with_data(bar, sizeof(GColor)); GColor *color_ptr = layer_get_data(s_scroll_items.success_bars[i]); *color_ptr = color; layer_set_update_proc(s_scroll_items.success_bars[i], bar_draw); scroll_layer_add_child(s_scroll_layer, s_scroll_items.success_bars[i]); } } void scroll_layer_remove_items() { // Destroy items for (int i = 0; i < MAX_ITEMS; i++) { // TextLayers text_layer_destroy(s_scroll_items.texts[i]); text_layer_destroy(s_scroll_items.numbers[i]); // BitmapLayers bitmap_layer_destroy(s_scroll_items.backgrounds[i]); bitmap_layer_destroy(s_scroll_items.plus_buttons[i]); bitmap_layer_destroy(s_scroll_items.minus_buttons[i]); // Layers layer_destroy(s_scroll_items.success_bars[i]); // Destroy the pointers s_scroll_items.texts[i] = NULL; s_scroll_items.numbers[i] = NULL; s_scroll_items.backgrounds[i] = NULL; s_scroll_items.plus_buttons[i] = NULL; s_scroll_items.minus_buttons[i] = NULL; s_scroll_items.success_bars[i] = NULL; } } void scroll_layer_update_scrollbar() { GRect scroll_box = layer_get_bounds(s_scroll_bar_layer); GRect scroll_frame = layer_get_frame(s_scroll_bar_layer); if (s_scroll_items.page_count == 2) { scroll_box.size.h = 82; scroll_frame.size.h = 82; s_scroll_bar_current_bitmap = s_scroll_bar_half_bitmap; } else if (s_scroll_items.page_count == 3) { scroll_box.size.h = 52; scroll_frame.size.h = 52; s_scroll_bar_current_bitmap = s_scroll_bar_third_bitmap; } else { scroll_box.size.h = 160; scroll_frame.size.h = 160; s_scroll_bar_current_bitmap = s_scroll_bar_full_bitmap; } layer_set_bounds(s_scroll_bar_layer, scroll_box); layer_set_frame(s_scroll_bar_layer, scroll_frame); layer_mark_dirty(s_scroll_bar_layer); } // ------------ TOUCH ------------ static void touch_handler(const TouchEvent *event, void *context) { // Get touch point GPoint point = GPoint(event->x, event->y); // First item buttons if (grect_contains_point(&item_1_plus_button, &point)) { int element = 0 + (s_scroll_page * MAX_UI_ITEMS); if (element >= s_scroll_items.items->num_items) { return; } if (event->type == TouchEvent_Touchdown) { // Change background to pressed bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_plus_pressed_bitmap); // Update numbers s_scroll_items.items->items[element].successes++; int total = s_scroll_items.items->items[element].successes + s_scroll_items.items->items[element].fails; float percentage = (float)s_scroll_items.items->items[element].successes / total; GColor color = get_color_float(percentage); fill_percentage_buffer(&s_scroll_items, element, total, percentage); text_layer_set_text_color(s_scroll_items.numbers[element], color); text_layer_set_text(s_scroll_items.numbers[element], s_scroll_items.numbers_buffer[element]); // Update the percentage bar int width = (PERCENTAGE_BAR_WIDTH) * percentage; GRect bar = GRect(31, (element * ITEM_UI_HEIGHT) + 40, width, 4); GColor *color_ptr = layer_get_data(s_scroll_items.success_bars[element]); *color_ptr = color; layer_set_frame(s_scroll_items.success_bars[element], bar); } else if (event->type == TouchEvent_Liftoff) { // Reset the background bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_bitmap); } } if (grect_contains_point(&item_1_minus_button, &point)) { int element = 0 + (s_scroll_page * MAX_UI_ITEMS); if (element >= s_scroll_items.items->num_items) { return; } if (event->type == TouchEvent_Touchdown) { // Change background to pressed bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_minus_pressed_bitmap); s_scroll_items.items->items[element].fails++; int total = s_scroll_items.items->items[element].successes + s_scroll_items.items->items[element].fails; float percentage = (float)s_scroll_items.items->items[element].successes / total; GColor color = get_color_float(percentage); fill_percentage_buffer(&s_scroll_items, element, total, percentage); text_layer_set_text_color(s_scroll_items.numbers[element], color); text_layer_set_text(s_scroll_items.numbers[element], s_scroll_items.numbers_buffer[element]); // Update the percentage bar int width = (PERCENTAGE_BAR_WIDTH) * percentage; GRect bar = GRect(31, (element * ITEM_UI_HEIGHT) + 40, width, 4); GColor *color_ptr = layer_get_data(s_scroll_items.success_bars[element]); *color_ptr = color; layer_set_frame(s_scroll_items.success_bars[element], bar); } else if (event->type == TouchEvent_Liftoff) { // Reset the background bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_bitmap); } } // Second item buttons if (grect_contains_point(&item_2_plus_button, &point)) { int element = 1 + (s_scroll_page * MAX_UI_ITEMS); if (element >= s_scroll_items.items->num_items) { return; } if (event->type == TouchEvent_Touchdown) { // Change background to pressed bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_plus_pressed_bitmap); s_scroll_items.items->items[element].successes++; int total = s_scroll_items.items->items[element].successes + s_scroll_items.items->items[element].fails; float percentage = (float)s_scroll_items.items->items[element].successes / total; GColor color = get_color_float(percentage); fill_percentage_buffer(&s_scroll_items, element, total, percentage); text_layer_set_text_color(s_scroll_items.numbers[element], color); text_layer_set_text(s_scroll_items.numbers[element], s_scroll_items.numbers_buffer[element]); // Update the percentage bar int width = (PERCENTAGE_BAR_WIDTH) * percentage; GRect bar = GRect(31, (element * ITEM_UI_HEIGHT) + 40, width, 4); GColor *color_ptr = layer_get_data(s_scroll_items.success_bars[element]); *color_ptr = color; layer_set_frame(s_scroll_items.success_bars[element], bar); } else if (event->type == TouchEvent_Liftoff) { // Reset the background bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_bitmap); } } if (grect_contains_point(&item_2_minus_button, &point)) { int element = 1 + (s_scroll_page * MAX_UI_ITEMS); if (element >= s_scroll_items.items->num_items) { return; } if (event->type == TouchEvent_Touchdown) { // Change background to pressed bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_minus_pressed_bitmap); s_scroll_items.items->items[element].fails++; int total = s_scroll_items.items->items[element].successes + s_scroll_items.items->items[element].fails; float percentage = (float)s_scroll_items.items->items[element].successes / total; GColor color = get_color_float(percentage); fill_percentage_buffer(&s_scroll_items, element, total, percentage); text_layer_set_text_color(s_scroll_items.numbers[element], color); text_layer_set_text(s_scroll_items.numbers[element], s_scroll_items.numbers_buffer[element]); // Update the percentage bar int width = (PERCENTAGE_BAR_WIDTH) * percentage; GRect bar = GRect(31, (element * ITEM_UI_HEIGHT) + 40, width, 4); GColor *color_ptr = layer_get_data(s_scroll_items.success_bars[element]); *color_ptr = color; layer_set_frame(s_scroll_items.success_bars[element], bar); } else if (event->type == TouchEvent_Liftoff) { // Reset the background bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_bitmap); } } // Thisrd item buttons if (grect_contains_point(&item_3_plus_button, &point)) { int element = 2 + (s_scroll_page * MAX_UI_ITEMS); if (element >= s_scroll_items.items->num_items) { return; } if (event->type == TouchEvent_Touchdown) { // Change background to pressed bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_plus_pressed_bitmap); s_scroll_items.items->items[element].successes++; int total = s_scroll_items.items->items[element].successes + s_scroll_items.items->items[element].fails; float percentage = (float)s_scroll_items.items->items[element].successes / total; GColor color = get_color_float(percentage); fill_percentage_buffer(&s_scroll_items, element, total, percentage); text_layer_set_text_color(s_scroll_items.numbers[element], color); text_layer_set_text(s_scroll_items.numbers[element], s_scroll_items.numbers_buffer[element]); // Update the percentage bar int width = (PERCENTAGE_BAR_WIDTH) * percentage; GRect bar = GRect(31, (element * ITEM_UI_HEIGHT) + 40, width, 4); GColor *color_ptr = layer_get_data(s_scroll_items.success_bars[element]); *color_ptr = color; layer_set_frame(s_scroll_items.success_bars[element], bar); } else if (event->type == TouchEvent_Liftoff) { // Reset the background bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_bitmap); } } if (grect_contains_point(&item_3_minus_button, &point)) { int element = 2 + (s_scroll_page * MAX_UI_ITEMS); if (element >= s_scroll_items.items->num_items) { return; } if (event->type == TouchEvent_Touchdown) { // Change background to pressed bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_minus_pressed_bitmap); s_scroll_items.items->items[element].fails++; int total = s_scroll_items.items->items[element].successes + s_scroll_items.items->items[element].fails; float percentage = (float)s_scroll_items.items->items[element].successes / total; GColor color = get_color_float(percentage); fill_percentage_buffer(&s_scroll_items, element, total, percentage); text_layer_set_text_color(s_scroll_items.numbers[element], color); text_layer_set_text(s_scroll_items.numbers[element], s_scroll_items.numbers_buffer[element]); // Update the percentage bar int width = (PERCENTAGE_BAR_WIDTH) * percentage; GRect bar = GRect(31, (element * ITEM_UI_HEIGHT) + 40, width, 4); GColor *color_ptr = layer_get_data(s_scroll_items.success_bars[element]); *color_ptr = color; layer_set_frame(s_scroll_items.success_bars[element], bar); } else if (event->type == TouchEvent_Liftoff) { // Reset the background bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_bitmap); } } } // ------------ INITS ------------ void scrolllayer_init(Layer *parent, Window *window) { s_scroll_y = 0; s_scroll_page = 0; GRect bounds = SCROLLLAYER_FRAME_RECT; // Load settings app_settings = settings_get(); // Load custom fonts s_scrolllayer_font = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_SLKSCR_16)); s_scrolllayer_font_small = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_SLKSCR_8)); // Add touch areas item_1_plus_button = ITEM_1_PLUS_BUTTON_RECT; item_1_minus_button = ITEM_1_MINUS_BUTTON_RECT; item_2_plus_button = ITEM_2_PLUS_BUTTON_RECT; item_2_minus_button = ITEM_2_MINUS_BUTTON_RECT; item_3_plus_button = ITEM_3_PLUS_BUTTON_RECT; item_3_minus_button = ITEM_3_MINUS_BUTTON_RECT; // Load bitmaps s_background_bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_ITEM_BACKGROUND); s_plus_bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_PLUS_BUTTON); s_minus_bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_MINUS_BUTTON); s_background_plus_pressed_bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_BACKGROUND_PLUS_PRESSED); s_background_minus_pressed_bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_BACKGROUND_MINUS_PRESSED); s_scroll_bar_full_bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_SCROLL_BAR_FULL); s_scroll_bar_half_bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_SCROLL_BAR_HALF); s_scroll_bar_third_bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_SCROLL_BAR_THIRD); // Create ScrollLayer s_scroll_layer = scroll_layer_create(bounds); scroll_layer_set_content_size( s_scroll_layer, GSize(bounds.size.w, MAX_ITEMS * ITEM_UI_HEIGHT) ); // Remove shadow scroll_layer_set_shadow_hidden(s_scroll_layer, true); // Button scroll window_set_click_config_provider(window, click_config_provider); // Get entries s_scroll_items.items = items_get(); // Add items scroll_layer_add_items(); // Add ScrollLayer layer_add_child(parent, scroll_layer_get_layer(s_scroll_layer)); // Add scroll bar GRect scroll_box = SCROLL_BAR_FRAME_RECT; if (s_scroll_items.page_count == 2) { scroll_box.size.h = 82; s_scroll_bar_layer = layer_create(scroll_box); s_scroll_bar_current_bitmap = s_scroll_bar_half_bitmap; } else if (s_scroll_items.page_count == 3) { scroll_box.size.h = 52; s_scroll_bar_layer = layer_create(scroll_box); s_scroll_bar_current_bitmap = s_scroll_bar_third_bitmap; } else { scroll_box.size.h = 160; s_scroll_bar_layer = layer_create(scroll_box); s_scroll_bar_current_bitmap = s_scroll_bar_full_bitmap; } layer_set_update_proc(s_scroll_bar_layer, scroll_bar_draw); layer_add_child(parent, s_scroll_bar_layer); // Register touch handler touch_service_subscribe(touch_handler, NULL); } void scrolllayer_deinit() { // Destroy settings app_settings = NULL; // Unload fonts fonts_unload_custom_font(s_scrolllayer_font); fonts_unload_custom_font(s_scrolllayer_font_small); // Unsubscribe touch touch_service_unsubscribe(); // Destroy ScrollLayer scroll_layer_destroy(s_scroll_layer); // Destroy bitmaps gbitmap_destroy(s_background_bitmap); gbitmap_destroy(s_plus_bitmap); gbitmap_destroy(s_minus_bitmap); gbitmap_destroy(s_background_plus_pressed_bitmap); gbitmap_destroy(s_background_minus_pressed_bitmap); gbitmap_destroy(s_scroll_bar_full_bitmap); gbitmap_destroy(s_scroll_bar_half_bitmap); gbitmap_destroy(s_scroll_bar_third_bitmap); // Destroy scroll bar layer_destroy(s_scroll_bar_layer); // Destroy items scroll_layer_remove_items(); }