diff --git a/.gitmodules b/.gitmodules index 03fbf4a..a25d9e7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -37,3 +37,6 @@ [submodule "components/pax-codecs"] path = components/pax-codecs url = https://github.com/robotman2412/pax-codecs.git +[submodule "main/pax-keyboard"] + path = components/pax-keyboard + url = https://github.com/robotman2412/pax-keyboard diff --git a/README.md b/README.md index 40701b0..1b5c7f9 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Source code included as submodules is licensed separately, please check the foll | components/i2c-bno055 | MIT | Nicolai Electronics | | components/mch2022-rp2040 | MIT | Renze Nicolai | | components/pax-graphics | MIT | Julian Scheffers | +| components/pax-keyboard | MIT | Julian Scheffers | | components/sdcard | MIT | Nicolai Electronics | | components/spi-ice40 | MIT | Nicolai Electronics | | components/spi-ili9341 | MIT | Nicolai Electronics | diff --git a/components/pax-graphics b/components/pax-graphics index 8e603e9..36049d7 160000 --- a/components/pax-graphics +++ b/components/pax-graphics @@ -1 +1 @@ -Subproject commit 8e603e9ca73a282a80e45e74160ab6c7c7fa4fff +Subproject commit 36049d7deb159c835eee6a5aa021b654bd3dd83b diff --git a/components/pax-keyboard b/components/pax-keyboard new file mode 160000 index 0000000..adad199 --- /dev/null +++ b/components/pax-keyboard @@ -0,0 +1 @@ +Subproject commit adad199c55e91f68d3e162b48f4e37816ef95c9a diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index f48ff6d..bbb07a6 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -4,7 +4,6 @@ idf_component_register( "fpga_test.c" "graphics_wrapper.c" "menu.c" - "pax_keyboard.c" "rp2040_updater.c" "settings.c" "system_wrapper.c" diff --git a/main/bootscreen.c b/main/bootscreen.c index 548d77e..c1fd43f 100644 --- a/main/bootscreen.c +++ b/main/bootscreen.c @@ -9,6 +9,8 @@ extern const uint8_t mch2022_logo_png_start[] asm("_binary_mch2022_logo_png_star extern const uint8_t mch2022_logo_png_end[] asm("_binary_mch2022_logo_png_end"); void display_boot_screen(pax_buf_t* pax_buffer, ILI9341* ili9341, const char* text) { + const pax_font_t *font = pax_get_font("saira regular"); + pax_noclip(pax_buffer); pax_background(pax_buffer, 0xFFFFFF); pax_buf_t logo; @@ -16,7 +18,7 @@ void display_boot_screen(pax_buf_t* pax_buffer, ILI9341* ili9341, const char* te pax_draw_image(pax_buffer, &logo, (320 / 2) - (212 / 2), ((240 - 32 - 10) / 2) - (160 / 2)); pax_buf_destroy(&logo); - pax_vec1_t size = pax_text_size(NULL, 18, text); - pax_draw_text(pax_buffer, 0xFF000000, NULL, 18, (320 / 2) - (size.x / 2), 240 - 32, text); + pax_vec1_t size = pax_text_size(font, 18, text); + pax_draw_text(pax_buffer, 0xFF000000, font, 18, (320 / 2) - (size.x / 2), 240 - 32, text); ili9341_write(ili9341, pax_buffer->buf); } diff --git a/main/graphics_wrapper.c b/main/graphics_wrapper.c index b4756ca..9192935 100644 --- a/main/graphics_wrapper.c +++ b/main/graphics_wrapper.c @@ -29,9 +29,13 @@ esp_err_t graphics_task(pax_buf_t* pax_buffer, ILI9341* ili9341, menu_t* menu, } bool keyboard(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, float aPosX, float aPosY, float aWidth, float aHeight, const char* aTitle, const char* aHint, char* aOutput, size_t aOutputSize) { + const pax_font_t *font = pax_get_font("saira regular"); bool accepted = false; pkb_ctx_t kb_ctx; - pkb_init(pax_buffer, &kb_ctx, aOutput); + pkb_init(pax_buffer, &kb_ctx, 1024); + pkb_set_content(&kb_ctx, aOutput); + kb_ctx.kb_font = font; + kb_ctx.text_font = font; pax_col_t fgColor = 0xFF000000; pax_col_t bgColor = 0xFFFFFFFF; @@ -42,7 +46,7 @@ bool keyboard(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, pax_col_t selColor = 0xff007fff; kb_ctx.text_col = borderColor; - kb_ctx.sel_text_col = selColor; + kb_ctx.sel_text_col = bgColor; kb_ctx.sel_col = selColor; kb_ctx.bg_col = bgColor; @@ -58,9 +62,9 @@ bool keyboard(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, pax_simple_rect(pax_buffer, titleBgColor, aPosX, aPosY, aWidth, titleHeight); pax_simple_line(pax_buffer, titleColor, aPosX + 1, aPosY + titleHeight, aPosX + aWidth - 2, aPosY + titleHeight - 1); pax_clip(pax_buffer, aPosX + 1, aPosY + 1, aWidth - 2, titleHeight - 2); - pax_draw_text(pax_buffer, titleColor, NULL, titleHeight - 2, aPosX + 1, aPosY + 1, aTitle); + pax_draw_text(pax_buffer, titleColor, font, titleHeight - 2, aPosX + 1, aPosY + 1, aTitle); pax_clip(pax_buffer, aPosX + 1, aPosY + aHeight - hintHeight, aWidth - 2, hintHeight); - pax_draw_text(pax_buffer, borderColor, NULL, hintHeight - 2, aPosX + 1, aPosY + aHeight - hintHeight, aHint); + pax_draw_text(pax_buffer, borderColor, font, hintHeight - 2, aPosX + 1, aPosY + aHeight - hintHeight, aHint); pax_noclip(pax_buffer); kb_ctx.x = aPosX + 1; diff --git a/main/include/pax_keyboard.h b/main/include/pax_keyboard.h deleted file mode 100644 index debd962..0000000 --- a/main/include/pax_keyboard.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - MIT License - - Copyright (c) 2022 Julian Scheffers - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -#ifndef PAX_KEYBOARD_H -#define PAX_KEYBOARD_H - -#include -#include -#include - -// A number of inputs supported by the PAX keyboard. -typedef enum { - // Represents no input being pressed. - PKB_NO_INPUT, - // Movement of the cursor. - PKB_UP, PKB_DOWN, PKB_LEFT, PKB_RIGHT, - // Delete to the left or the selection. Backspace key. - PKB_DELETE_BEFORE, - // Delete to the right or the selection. Delete key. - PKB_DELETE_AFTER, - // Switch between lower case, upper case and symbols. - PKB_MODESELECT, - // Enter a character. - PKB_CHARSELECT, - // The same thing as the shift key. - // Goes between PKB_LOWERCASE and PKB_UPPERCASE or PKB_NUMBERS and PKB_SYMBOLS. - PKB_SHIFT, -} pkb_input_t; - -// The type of keyboard currently selected. -typedef enum { - // Lowercase and ., - PKB_LOWERCASE, - // Uppercase and <> - PBK_UPPERCASE, - // Numbers and symbols 1/2 - PKB_NUMBERS, - // Symbols 2/2 - PKB_SYMBOLS, -} pkb_keyboard_t; - -// The PAX keyboard context used for drawing and alike. -typedef struct { - // Position on screen of the keyboard. - int x, y; - // Maximum size of the keyboard. - int width, height; - - // Content of the keyboard. - char *content; - // Size in bytes of capacity of the content buffer. - size_t content_cap; - - // Starting position of the selection in the text box. - int selection; - // Cursor position of the text box. - int cursor; - - // Cursor position of the keyboard. - int key_x, key_y; - // The currently held input. - pkb_input_t held; - // The time that holding the input started. - int64_t hold_start; - // The last time pkb_press was called. - int64_t last_press; - - // Whether the keyboard is multi-line. - bool multiline; - // Whether the keyboard is in insert mode. - bool insert; - // The board that is currently selected. - pkb_keyboard_t board_sel; - - // The font to use for the keyboard. - pax_font_t *kb_font; - // The font size to use for the keyboard. - float kb_font_size; - // The font to use for the text. - pax_font_t *text_font; - // The font size to use for the text. - float text_font_size; - // The text color to use. - pax_col_t text_col; - // The text color to use when a character is being held down. - pax_col_t sel_text_col; - // The selection color to use. - pax_col_t sel_col; - // The background color to use. - pax_col_t bg_col; - - // Whether something has changed since last draw. - bool dirty; - // Whether the text has changed since last draw. - bool text_dirty; - // Whether the keyboard has changed since last draw. - bool kb_dirty; - // Whether just the selected character has changed since last draw. - bool sel_dirty; - // Previous cursor position of the keyboard. - // Used for sel_dirty. - int last_key_x, last_key_y; - - // Indicates that the input has been accepted. - bool input_accepted; -} pkb_ctx_t; - -// Initialise the context with default settings. -void pkb_init (pax_buf_t *buf, pkb_ctx_t *ctx, char* data); -// Free any memory associated with the context. -void pkb_destroy(pkb_ctx_t *ctx); - -// Redraw the complete on-screen keyboard. -void pkb_render (pax_buf_t *buf, pkb_ctx_t *ctx); -// Redraw only the changed parts of the on-screen keyboard. -void pkb_redraw (pax_buf_t *buf, pkb_ctx_t *ctx); - -// The loop that allows input repeating. -void pkb_loop (pkb_ctx_t *ctx); - -// A pressing of the input. -void pkb_press (pkb_ctx_t *ctx, pkb_input_t input); -// A relealing of the input. -void pkb_release(pkb_ctx_t *ctx, pkb_input_t input); - -#endif //PAX_KEYBOARD_H diff --git a/main/menu.c b/main/menu.c index 04ed07e..c6a57a3 100644 --- a/main/menu.c +++ b/main/menu.c @@ -183,6 +183,7 @@ void menu_render(pax_buf_t *aBuffer, menu_t* aMenu, float aPosX, float aPosY, fl pax_col_t titleBgColor = aColor; pax_col_t scrollbarBgColor = 0xFFCCCCCC; pax_col_t scrollbarFgColor = 0xFF555555; + const pax_font_t *font = pax_get_font("saira regular"); float entry_height = 18 + 2; size_t maxItems = aHeight / entry_height; @@ -196,7 +197,7 @@ void menu_render(pax_buf_t *aBuffer, menu_t* aMenu, float aPosX, float aPosY, fl pax_simple_rect(aBuffer, titleBgColor, aPosX, posY, aWidth, entry_height); pax_simple_line(aBuffer, titleColor, aPosX + 1, aPosY + entry_height, aPosX + aWidth - 2, aPosY + entry_height - 1); pax_clip(aBuffer, aPosX + 1, posY + 1, aWidth - 2, entry_height - 2); - pax_draw_text(aBuffer, titleColor, NULL, entry_height - 2, aPosX + 1, posY + 1, aMenu->title); + pax_draw_text(aBuffer, titleColor, font, entry_height - 2, aPosX + 1, posY + 1, aMenu->title); pax_noclip(aBuffer); posY += entry_height; } @@ -219,12 +220,12 @@ void menu_render(pax_buf_t *aBuffer, menu_t* aMenu, float aPosX, float aPosY, fl if (index == aMenu->position) { pax_simple_rect(aBuffer, fgColor, aPosX + 1, posY, aWidth - 2, entry_height); pax_clip(aBuffer, aPosX + 1, posY + 1, aWidth - 4, entry_height - 2); - pax_draw_text(aBuffer, bgTextColor, NULL, entry_height - 2, aPosX + 1, posY + 1, item->label); + pax_draw_text(aBuffer, bgTextColor, font, entry_height - 2, aPosX + 1, posY + 1, item->label); pax_noclip(aBuffer); } else { pax_simple_rect(aBuffer, bgColor, aPosX + 1, posY, aWidth - 2, entry_height); pax_clip(aBuffer, aPosX + 1, posY + 1, aWidth - 4, entry_height - 2); - pax_draw_text(aBuffer, fgColor, NULL, entry_height - 2, aPosX + 1, posY + 1, item->label); + pax_draw_text(aBuffer, fgColor, font, entry_height - 2, aPosX + 1, posY + 1, item->label); pax_noclip(aBuffer); } posY += entry_height; diff --git a/main/menus/dev.c b/main/menus/dev.c index 0ef6acc..c654d27 100644 --- a/main/menus/dev.c +++ b/main/menus/dev.c @@ -30,9 +30,10 @@ typedef enum action { } menu_dev_action_t; void render_dev_help(pax_buf_t* pax_buffer) { + const pax_font_t *font = pax_get_font("saira regular"); pax_background(pax_buffer, 0xFFFFFF); pax_noclip(pax_buffer); - pax_draw_text(pax_buffer, 0xFF000000, NULL, 18, 5, 240 - 19, "[A] accept [B] back"); + pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 19, "[A] accept [B] back"); } void menu_dev(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) { diff --git a/main/menus/launcher.c b/main/menus/launcher.c index e65e1dd..86d073a 100644 --- a/main/menus/launcher.c +++ b/main/menus/launcher.c @@ -27,7 +27,8 @@ typedef struct { void menu_launcher(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) { menu_t* menu = menu_alloc("Apps"); - + const pax_font_t *font = pax_get_font("saira regular"); + appfs_handle_t appfs_fd = APPFS_INVALID_FD; while (1) { appfs_fd = appfsNextEntry(appfs_fd); @@ -45,7 +46,7 @@ void menu_launcher(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili pax_background(pax_buffer, 0xFFFFFF); pax_noclip(pax_buffer); - pax_draw_text(pax_buffer, 0xFF000000, NULL, 18, 5, 240 - 19, "[A] start app [B] back"); + pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 19, "[A] start app [B] back"); bool quit = false; diff --git a/main/menus/settings.c b/main/menus/settings.c index 04f0df3..71b142f 100644 --- a/main/menus/settings.c +++ b/main/menus/settings.c @@ -31,9 +31,10 @@ typedef enum action { } menu_settings_action_t; void render_settings_help(pax_buf_t* pax_buffer) { + const pax_font_t *font = pax_get_font("saira regular"); pax_background(pax_buffer, 0xFFFFFF); pax_noclip(pax_buffer); - pax_draw_text(pax_buffer, 0xFF000000, NULL, 18, 5, 240 - 19, "[A] accept [B] back"); + pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 19, "[A] accept [B] back"); } void menu_settings(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) { diff --git a/main/menus/start.c b/main/menus/start.c index 83218df..7dba283 100644 --- a/main/menus/start.c +++ b/main/menus/start.c @@ -24,9 +24,10 @@ typedef enum action { } menu_start_action_t; void render_start_help(pax_buf_t* pax_buffer) { + const pax_font_t *font = pax_get_font("saira regular"); pax_background(pax_buffer, 0xFFFFFF); pax_noclip(pax_buffer); - pax_draw_text(pax_buffer, 0xFF000000, NULL, 18, 5, 240 - 19, "[A] accept"); + pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 19, "[A] accept"); } void menu_start(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) { diff --git a/main/menus/wifi.c b/main/menus/wifi.c index 962f40e..7a1bfc3 100644 --- a/main/menus/wifi.c +++ b/main/menus/wifi.c @@ -60,9 +60,10 @@ typedef enum action { } menu_wifi_action_t; void render_wifi_help(pax_buf_t* pax_buffer) { + const pax_font_t *font = pax_get_font("saira regular"); pax_background(pax_buffer, 0xFFFFFF); pax_noclip(pax_buffer); - pax_draw_text(pax_buffer, 0xFF000000, NULL, 18, 5, 240 - 19, "[A] accept [B] back"); + pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 19, "[A] accept [B] back"); } void wifi_show(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341); @@ -440,12 +441,7 @@ void wifi_setup(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili934 /* ==== scanning phase ==== */ if (scan) { // Show a little bit of text. - char *text = "Scanning..."; - pax_vec1_t dims = pax_text_size(NULL, 1, text); - float scale = pax_buffer->width / dims.x; - pax_background(pax_buffer, 0xffffffff); - pax_draw_text(pax_buffer, 0xff000000, NULL, scale, 0, (pax_buffer->height - dims.y*scale)/2, text); - ili9341_write(ili9341, pax_buffer->buf); + display_boot_screen(pax_buffer, ili9341, "Scanning WiFi networks..."); // Scan for networks. wifi_ap_record_t *aps; diff --git a/main/pax_keyboard.c b/main/pax_keyboard.c deleted file mode 100644 index 54ebb55..0000000 --- a/main/pax_keyboard.c +++ /dev/null @@ -1,791 +0,0 @@ -/* - MIT License - - Copyright (c) 2022 Julian Scheffers - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -#include -#include -#include -#include - -/* ==== Miscellaneous ==== */ - -// Initialise the context with default settings. -void pkb_init(pax_buf_t *buf, pkb_ctx_t *ctx, char* data) { - // Allocate a bufffer. - char *buffer = NULL; - - if (data == NULL) { - buffer = malloc(4); - memset(buffer, 0, 4); - } else { - size_t length = strlen(data); - if (length < 4) length = 4; - buffer = malloc(length); - memset(buffer, 0, length); - strcpy(buffer, data); - } - - // Some defaults. - *ctx = (pkb_ctx_t) { - // Position on screen of the keyboard. - .x = 0, - .y = 0, - // Maximum size of the keyboard. - .width = buf->width, - .height = buf->height, - - // Content of the keyboard. - .content = buffer, - // Size in bytes of capacity of the content buffer. - .content_cap = 4, - - // Starting position of the selection in the text box. - .selection = 0, - // Cursor position of the text box. - .cursor = 0, - - // Cursor position of the keyboard. - .key_x = 3, - .key_y = 1, - // The currently held input. - .held = PKB_NO_INPUT, - // The time that holding the input started. - .hold_start = 0, - // The last time pkb_press was called. - .last_press = 0, - - // Whether the keyboard is multi-line. - .multiline = false, - // Whether the keyboard is in insert mode. - .insert = false, - // The board that is currently selected. - .board_sel = PKB_LOWERCASE, - - // The font to use for the keyboard. - .kb_font = PAX_FONT_DEFAULT, - // The font size to use for the keyboard. - .kb_font_size = 27, - // The font to use for the text. - .text_font = PAX_FONT_DEFAULT, - // The font size to use for the text. - .text_font_size = 18, - // The text color to use. - .text_col = 0xffffffff, - // The text color to use when a character is being held down. - .sel_text_col = 0xff000000, - // The selection color to use. - .sel_col = 0xff007fff, - // The background color to use. - .bg_col = 0xff000000, - - // Whether something has changed since last draw. - .dirty = true, - // Whether the text has changed since last draw. - .text_dirty = true, - // Whether the keyboard has changed since last draw. - .kb_dirty = true, - // Whether just the selected character has changed since last draw. - .sel_dirty = true, - // Previous cursor position of the keyboard. - // Used for sel_dirty. - .last_key_x = 3, - .last_key_y = 1, - - // Indicates that the input has been accepted. - .input_accepted = false, - }; - - // TODO: Pick fancier text sizes. -} - -// Free any memory associated with the context. -void pkb_destroy(pkb_ctx_t *ctx) { - free(ctx->content); - ctx->content = NULL; - ctx->content_cap = 0; -} - -const char *uppercase_board[] = { - "QWERTYUIOP", - "ASDFGHJKL", - " ZXCVBNM ", - " < > ", - "<", ">", -}; -const char *lowercase_board[] = { - "qwertyuiop", - "asdfghjkl", - " zxcvbnm ", - " , . ", - ",", ".", -}; -const char *number_board[] = { - "1234567890", - "@#$_&-+()/", - " *\"';:!? ", - " = \\ ", - "=", "\\", -}; -const char *symbols_board[] = { - "()[]{}`~", - "/|\\+-_=", - " ^%<>'\" ", - " , . ", - ",", ".", -}; -const char **boards[] = { - lowercase_board, uppercase_board, - number_board, symbols_board, -}; - -/* ==== Special key art ==== */ - -// Art for the accept key. -// Expects x to be the horizontal center of the key. -static void pkb_art_accept(pax_buf_t *buf, pkb_ctx_t *ctx, float x, float y, float dx, bool selected) { - pax_col_t col = selected && ctx->held == PKB_CHARSELECT ? ctx->sel_text_col : ctx->text_col; - float scale = fminf(ctx->kb_font_size - 4, dx - 4); - - pax_push_2d (buf); - pax_apply_2d (buf, matrix_2d_translate(x-dx/2+2, y+2)); - pax_apply_2d (buf, matrix_2d_scale(scale, scale)); - - pax_draw_line(buf, col, 0.25, 0.5, 0.5, 1); - pax_draw_line(buf, col, 0.5, 1, 1, 0); - - pax_pop_2d (buf); -} - - -// Art for the backspace key. -// Expects x to be the horizontal center of the key. -static void pkb_art_bksp(pax_buf_t *buf, pkb_ctx_t *ctx, float x, float y, float dx, bool selected) { - pax_col_t col = selected && ctx->held == PKB_CHARSELECT ? ctx->sel_text_col : ctx->text_col; - float scale = fminf(ctx->kb_font_size - 4, dx - 4); - - pax_push_2d (buf); - pax_apply_2d (buf, matrix_2d_translate(x-dx/2+2, y+2)); - pax_apply_2d (buf, matrix_2d_scale(scale, scale)); - - // The stopper. - pax_draw_line(buf, col, 0, 0.25, 0, 0.75); - // The arrow. - pax_draw_line(buf, col, 0.1, 0.5, 0.35, 0.25); - pax_draw_line(buf, col, 0.1, 0.5, 0.35, 0.75); - pax_draw_line(buf, col, 0.1, 0.5, 1, 0.5); - - pax_pop_2d (buf); -} - -// Art for the shift key. -// Expects x to be the horizontal center of the key. -static void pkb_art_shift(pax_buf_t *buf, pkb_ctx_t *ctx, float x, float y, float dx, bool selected) { - bool active = ctx->board_sel & 1; - pax_col_t col = selected && ctx->held == PKB_CHARSELECT ? ctx->sel_text_col : ctx->text_col; - float scale = fminf(ctx->kb_font_size - 4, dx - 4); - - pax_push_2d (buf); - pax_apply_2d(buf, matrix_2d_translate(x, y+2)); - pax_apply_2d(buf, matrix_2d_scale(scale, scale)); - - if (active) { - // Filled in shift key. - pax_draw_tri (buf, col, -0.5, 0.5, 0, 0, 0.5, 0.5); - pax_draw_rect(buf, col, -0.25, 0.5, 0.5, 0.5); - } else { - // Outlined shift key. - pax_draw_line(buf, col, 0, 0, 0.5, 0.5); - pax_draw_line(buf, col, 0.5, 0.5, 0.25, 0.5); - pax_draw_line(buf, col, 0.25, 0.5, 0.25, 1); - pax_draw_line(buf, col, 0.25, 1, -0.25, 1); - pax_draw_line(buf, col, -0.25, 0.5, -0.25, 1); - pax_draw_line(buf, col, -0.5, 0.5, -0.25, 0.5); - pax_draw_line(buf, col, 0, 0, -0.5, 0.5); - } - - pax_pop_2d (buf); -} - -// Art for the letters/numbers key. -// Expects x to be the horizontal center of the key. -static void pkb_art_select(pax_buf_t *buf, pkb_ctx_t *ctx, float x, float y, float dx, bool selected) { - pax_col_t col = selected && ctx->held == PKB_CHARSELECT ? ctx->sel_text_col : ctx->text_col; - - // Pick the stuff to show. - char *short_str; - char *long_str; - if (ctx->board_sel == PKB_NUMBERS) { - // Show some symbols. - short_str = "%"; - long_str = "%&~"; - } else if (ctx->board_sel == PKB_SYMBOLS) { - // Show some letters. - short_str = "A"; - long_str = "Abc"; - } else { - // Show some numbers. - short_str = "#"; - long_str = "123"; - } - - // Calculate font size. - char *str = long_str; - pax_vec1_t dims = pax_text_size(ctx->kb_font, 0, str); - int font_size = 9;//(dx - 4) / dims.x * dims.y; - if (font_size < dims.y) { - str = short_str; - dims = pax_text_size(ctx->kb_font, 0, str); - font_size = 9;//(dx - 4) / dims.x * dims.y; - } - dims = pax_text_size(ctx->kb_font, font_size, str); - - // Now draw it. - pax_push_2d (buf); - pax_apply_2d (buf, matrix_2d_translate(x-dims.x/2, y+(ctx->kb_font_size-font_size)/2)); - pax_draw_text(buf, col, ctx->kb_font, font_size, 0, 0, str); - pax_pop_2d (buf); -} - -/* ==== Rendering ==== */ - -// Draw one key of the keyboard. -// Expects x to be the horizontal center of the key. -static void pkb_char(pax_buf_t *buf, pkb_ctx_t *ctx, float x, float y, float dx, char *text, bool selected) { - pax_vec1_t dims = pax_text_size(ctx->kb_font, ctx->kb_font_size, text); - - if (selected && ctx->held == PKB_CHARSELECT) { - // Infilll! - pax_draw_rect(buf, ctx->sel_col, x-dx/2, y, dx, ctx->kb_font_size); - pax_draw_text(buf, ctx->sel_text_col, ctx->kb_font, ctx->kb_font_size, x-dims.x*0.5, y, text); - } else { - pax_draw_text(buf, ctx->text_col, ctx->kb_font, ctx->kb_font_size, x-dims.x*0.5, y, text); - - // Outline? - if (selected) { - pax_push_2d(buf); - pax_apply_2d(buf, matrix_2d_translate(-dx/2, 0)); - pax_draw_line(buf, ctx->sel_col, x, y, x + dx - 1, y); - pax_draw_line(buf, ctx->sel_col, x, y+ctx->kb_font_size-1, x + dx - 1, y+ctx->kb_font_size-1); - pax_draw_line(buf, ctx->sel_col, x + dx - 1, y, x + dx - 1, y+ctx->kb_font_size-1); - pax_draw_line(buf, ctx->sel_col, x, y, x, y+ctx->kb_font_size-1); - pax_pop_2d(buf); - } - } -} - -// Draw one full row of the keyboard. -static void pkb_row(pax_buf_t *buf, pkb_ctx_t *ctx, int rownum, int selected, float dx, float y) { - // Calculate some stuff. - char *row = boards[ctx->board_sel][rownum]; - size_t len = strlen(row); - int x = ctx->x + (ctx->width - len * dx + dx) / 2; - char tmp[2] = {0,0}; - - // Show all of them. - for (int i = 0; i < len; i++) { - // Draw a KEY. - *tmp = row[i]; - pkb_char(buf, ctx, x, y, dx, tmp, selected == i); - - if (i == 0 && rownum == 2) { - // Draw shift key art. - pkb_art_shift(buf, ctx, x, y, dx, selected == i); - } else if (rownum == 2 && i == len - 1) { - // Draw the backspace key art. - pkb_art_bksp(buf, ctx, x, y, dx, selected == i); - } - - x += dx; - } -} - -// Draw a specific key in a row of the keyboard. -static void pkb_row_key(pax_buf_t *buf, pkb_ctx_t *ctx, int rownum, bool selected, float dx, float y, int keyno) { - // Calculate some stuff. - char *row = boards[ctx->board_sel][rownum]; - size_t len = strlen(row); - int x = ctx->x + (ctx->width - len * dx + dx) / 2 + dx * keyno; - char tmp[2] = {0,0}; - - // Show one of them. - *tmp = row[keyno]; - pax_draw_rect(buf, ctx->bg_col, x-dx/2, y, dx, ctx->kb_font_size); - pkb_char(buf, ctx, x, y, dx, tmp, selected); - - if (rownum == 2 && keyno == 0) { - // Draw the shift key art. - pkb_art_shift(buf, ctx, x, y, dx, selected); - } else if (rownum == 2 && keyno == len - 1) { - // Draw the backspace key art. - pkb_art_bksp(buf, ctx, x, y, dx, selected); - } -} - -// Draw just the board part. -static void pkb_render_keyb(pax_buf_t *buf, pkb_ctx_t *ctx, bool do_bg) { - // Draw background. - if (do_bg) { - pax_draw_rect(buf, ctx->bg_col, ctx->x, ctx->y + ctx->height - ctx->kb_font_size*4, ctx->width, ctx->kb_font_size*4); - } - - // Select the board to display. - char **board = boards[ctx->board_sel]; - float dx = ctx->width / 10; - float y = ctx->y + ctx->height - ctx->kb_font_size * 4; - - // Draw the first three rows. - for (int i = 0; i < 3; i ++) { - int sel = -1; - if (i == ctx->key_y) { - sel = ctx->key_x; - } - pkb_row(buf, ctx, i, sel, dx, y); - y += ctx->kb_font_size; - } - - // Spacebar row time. - bool space_sel = ctx->key_y == 3 && ctx->key_x > 1 && ctx->key_x < 7; - float x = ctx->x + (ctx->width - 8 * dx) / 2; - - // The thingy selector. - pkb_char(buf, ctx, x, y, dx, " ", ctx->key_y == 3 && ctx->key_x == 0); - pkb_art_select(buf, ctx, x, y, dx, ctx->key_y == 3 && ctx->key_x == 0); - x += 1.0 * dx; - // Left char. - pkb_char(buf, ctx, x, y, dx, board[4], ctx->key_y == 3 && ctx->key_x == 1); - x += 1.0 * dx; - - // SPACE. - if (space_sel && ctx->held == PKB_CHARSELECT) { - pax_draw_rect(buf, ctx->sel_col, x-dx/2, y, dx*5, ctx->kb_font_size); - pax_draw_rect(buf, ctx->sel_text_col, x, y + ctx->kb_font_size/3, dx*4, ctx->kb_font_size/3); - } else { - pax_draw_rect(buf, ctx->text_col, x, y + ctx->kb_font_size/3, dx*4, ctx->kb_font_size/3); - if (space_sel) { - // Outline rect? - pax_push_2d(buf); - pax_apply_2d(buf, matrix_2d_translate(-dx/2, 0)); - pax_draw_line(buf, ctx->sel_col, x, y, x + dx*5 - 1, y); - pax_draw_line(buf, ctx->sel_col, x, y+ctx->kb_font_size-1, x + dx*5 - 1, y+ctx->kb_font_size-1); - pax_draw_line(buf, ctx->sel_col, x + dx*5 - 1, y, x + dx*5 - 1, y+ctx->kb_font_size-1); - pax_draw_line(buf, ctx->sel_col, x, y, x, y+ctx->kb_font_size-1); - pax_pop_2d(buf); - } - } - - // Right char. - x += 5.0 * dx; - pkb_char(buf, ctx, x, y, dx, board[5], ctx->key_y == 3 && ctx->key_x == 7); - x += 1.0 * dx; - // The thingy acceptor. - pkb_char(buf, ctx, x, y, dx, " ", ctx->key_y == 3 && ctx->key_x == 8); - pkb_art_accept(buf, ctx, x, y, dx, ctx->key_y == 3 && ctx->key_x == 8); -} - -// Draw just the text part. -static void pkb_render_text(pax_buf_t *buf, pkb_ctx_t *ctx, bool do_bg) { - // Draw background. - if (do_bg) { - pax_draw_rect(buf, ctx->bg_col, ctx->x, ctx->y, ctx->width, ctx->height - ctx->kb_font_size*4); - } - if (ctx->key_y == -1) { - // Outline us. - pax_outline_rect(buf, ctx->sel_col, ctx->x, ctx->y, ctx->width, ctx->height - ctx->kb_font_size*4); - } - - // Some setup. - float x = ctx->x + 2; - float y = ctx->y + 2; - char tmp[2] = {0, 0}; - - // Draw everything. - for (int i = 0; i < strlen(ctx->content); i++) { - if (ctx->cursor == i) { - // The cursor in between the input. - pax_draw_line(buf, ctx->sel_col, x, y, x, y + ctx->text_font_size - 1); - } - - // The character of the input. - tmp[0] = ctx->content[i]; - pax_vec1_t dims = pax_text_size(ctx->text_font, ctx->text_font_size, tmp); - - if (x + dims.x > ctx->width - 2) { - // Word wrap. - x = 2; - y += ctx->text_font_size; - } - pax_draw_text(buf, ctx->text_col, ctx->text_font, ctx->text_font_size, x, y, tmp); - x += dims.x; - } - if (ctx->cursor == strlen(ctx->content)) { - // The cursor after the input. - pax_draw_line(buf, ctx->sel_col, x, y, x, y + ctx->text_font_size - 1); - } -} - -// Draw one specific key. -static void pkb_render_key(pax_buf_t *buf, pkb_ctx_t *ctx, int key_x, int key_y) { - if (key_y == -1) { - // If key_y is -1, the text box is selected to render. - pkb_render_text(buf, ctx, true); - return; - } - - // Select the board to display. - char **board = boards[ctx->board_sel]; - float dx = ctx->width / 10; - float y = ctx->y + ctx->height - ctx->kb_font_size * 4; - - if (key_y < 3) { - // Draw one of the first three rows. - y += ctx->kb_font_size * key_y; - pkb_row_key(buf, ctx, key_y, key_y == ctx->key_y && key_x == ctx->key_x, dx, y, key_x); - y += ctx->kb_font_size; - } else { - // Spacebar row time. - y += ctx->kb_font_size * 3; - bool space_sel = ctx->key_y == 3 && ctx->key_x > 1 && ctx->key_x < 7; - float x = ctx->x + (ctx->width - 8 * dx) / 2; - - // The thingy selector. - if (key_x == 0) { - pax_draw_rect(buf, ctx->bg_col, x-dx/2, y, dx, ctx->kb_font_size); - pkb_char(buf, ctx, x, y, dx, " ", ctx->key_y == 3 && ctx->key_x == 0); - pkb_art_select(buf, ctx, x, y, dx, ctx->key_y == 3 && ctx->key_x == 0); - } - x += 1.0 * dx; - if (key_x == 1) { - pax_draw_rect(buf, ctx->bg_col, x-dx/2, y, dx, ctx->kb_font_size); - pkb_char(buf, ctx, x, y, dx, board[4], ctx->key_y == 3 && ctx->key_x == 1); - } - x += 1.0 * dx; - - // SPACE. - if (space_sel && ctx->held == PKB_CHARSELECT) { - pax_draw_rect(buf, ctx->sel_col, x-dx/2, y, dx*5, ctx->kb_font_size); - pax_draw_rect(buf, ctx->sel_text_col, x, y + ctx->kb_font_size/3, dx*4, ctx->kb_font_size/3); - } else { - pax_draw_rect(buf, ctx->bg_col, x-dx/2, y, dx*5, ctx->kb_font_size); - pax_draw_rect(buf, ctx->text_col, x, y + ctx->kb_font_size/3, dx*4, ctx->kb_font_size/3); - if (space_sel) { - // Outline rect? - pax_push_2d(buf); - pax_apply_2d(buf, matrix_2d_translate(-dx/2, 0)); - pax_draw_line(buf, ctx->sel_col, x, y, x + dx*5 - 1, y); - pax_draw_line(buf, ctx->sel_col, x, y+ctx->kb_font_size-1, x + dx*5 - 1, y+ctx->kb_font_size-1); - pax_draw_line(buf, ctx->sel_col, x + dx*5 - 1, y, x + dx*5 - 1, y+ctx->kb_font_size-1); - pax_draw_line(buf, ctx->sel_col, x, y, x, y+ctx->kb_font_size-1); - pax_pop_2d(buf); - } - } - - // Right char. - x += 5.0 * dx; - if (key_x == 7) { - pax_draw_rect(buf, ctx->bg_col, x-dx/2, y, dx, ctx->kb_font_size); - pkb_char(buf, ctx, x, y, dx, board[5], ctx->key_y == 3 && ctx->key_x == 7); - } - x += 1.0 * dx; - // The thingy acceptor. - if (key_x == 8) { - pax_draw_rect(buf, ctx->bg_col, x-dx/2, y, dx, ctx->kb_font_size); - pkb_char(buf, ctx, x, y, dx, " ", ctx->key_y == 3 && ctx->key_x == 8); - pkb_art_accept(buf, ctx, x, y, dx, ctx->key_y == 3 && ctx->key_x == 8); - } - } -} - -// Redraw the complete on-screen keyboard. -void pkb_render(pax_buf_t *buf, pkb_ctx_t *ctx) { - if (matrix_2d_is_identity(buf->stack_2d.value) - && ctx->x == 0 && ctx->y == 0 - && ctx->width == buf->width - && ctx->height == buf->height) { - // We can just fill the entire screen. - pax_background(buf, ctx->bg_col); - } else { - // We'll need to fill a rectangle. - pax_draw_rect( - buf, ctx->bg_col, - ctx->x, ctx->y, - ctx->width, ctx->height - ); - } - - // Draw the board. - pkb_render_keyb(buf, ctx, false); - // Time to draw some text. - pkb_render_text(buf, ctx, false); - - // Mark as not dirty. - ctx->dirty = false; - ctx->kb_dirty = false; - ctx->sel_dirty = false; - ctx->text_dirty = false; - ctx->last_key_x = ctx->key_x; - ctx->last_key_y = ctx->key_y; -} - -// Redraw only the changed parts of the on-screen keyboard. -void pkb_redraw(pax_buf_t *buf, pkb_ctx_t *ctx) { - if (ctx->text_dirty) { - pkb_render_text(buf, ctx, true); - } - if (ctx->kb_dirty) { - pkb_render_keyb(buf, ctx, true); - } else if (ctx->sel_dirty) { - pkb_render_key(buf, ctx, ctx->last_key_x, ctx->last_key_y); - pkb_render_key(buf, ctx, ctx->key_x, ctx->key_y); - } - - // Mark as not dirty. - ctx->dirty = false; - ctx->kb_dirty = false; - ctx->sel_dirty = false; - ctx->text_dirty = false; - ctx->last_key_x = ctx->key_x; - ctx->last_key_y = ctx->key_y; -} - -/* ==== Text editing ==== */ - -// Handling of delete or backspace. -static void pkb_delete(pkb_ctx_t *ctx, bool is_backspace) { - size_t oldlen = strlen(ctx->content); - if (!is_backspace && ctx->cursor == oldlen) { - // No forward deleting at the end of the line. - return; - } else if (is_backspace && ctx->cursor == 0) { - // No backward deleting at the start of the line. - return; - } else if (!is_backspace) { - // Advanced backspace. - ctx->cursor ++; - } - - // Copy back everything including null terminator. - ctx->cursor --; - for (int i = ctx->cursor; i < oldlen; i++) { - ctx->content[i] = ctx->content[i+1]; - } - - // DECREMENT length. - if (oldlen * 2 < ctx->content_cap) { - // Not decrementing here is important as oldlen excludes the null terminator. - ctx->content_cap = oldlen; - ctx->content = realloc(ctx->content, ctx->content_cap); - } - ctx->text_dirty = true; -} - -// Handling of normal input. -static void pkb_append(pkb_ctx_t *ctx, char value) { - size_t oldlen = strlen(ctx->content); - if (oldlen + 2 >= ctx->content_cap) { - // Expand the buffer just a bit. - ctx->content_cap *= 2; - ctx->content = realloc(ctx->content, ctx->content_cap); - } - - // Copy over the remainder of the buffer. - // If there's no text this still copies the null terminator. - for (int i = oldlen; i >= ctx->cursor; i --) { - ctx->content[i + 1] = ctx->content[i]; - } - - // And finally insert at the character. - ctx->content[ctx->cursor] = value; - ctx->cursor ++; - ctx->text_dirty = true; -} - -/* ==== Input handling ==== */ - -// The loop that allows input repeating. -void pkb_loop(pkb_ctx_t *ctx) { - int64_t now = esp_timer_get_time(); - if (!ctx->held) return; - bool is_dir = (ctx->held >= PKB_UP) && (ctx->held <= PKB_RIGHT); - - if ((ctx->hold_start + 1000000 < now) || (is_dir && ctx->hold_start + 250000 < now)) { - // 8 repeats per second. - if (ctx->last_press + 125000 < now) { - pkb_press(ctx, ctx->held); - } - } -} - -// A pressing of the input. -void pkb_press(pkb_ctx_t *ctx, pkb_input_t input) { - char **board = boards[ctx->board_sel]; - ctx->last_press = esp_timer_get_time(); - switch (input) { - // Cursor movements. - size_t rowlen; - case PKB_UP: - ctx->key_y --; - if (ctx->key_y < -1) ctx->key_y = 3; - else if (ctx->key_y != -1) { - rowlen = strlen(board[ctx->key_y]); - if (ctx->key_x >= rowlen) ctx->key_x = rowlen - 1; - } - ctx->sel_dirty = true; - break; - - case PKB_DOWN: - ctx->key_y ++; - ctx->key_y %= 4; - rowlen = strlen(board[ctx->key_y]); - if (ctx->key_x >= rowlen) ctx->key_x = rowlen - 1; - ctx->sel_dirty = true; - break; - - case PKB_LEFT: - if (ctx->key_y == -1) { - if (ctx->cursor > 0) ctx->cursor --; - } else if (ctx->key_y == 3 && ctx->key_x > 1 && ctx->key_x < 7) { - ctx->key_x = 1; - } else { - ctx->key_x --; - if (ctx->key_x < 0) ctx->key_x = strlen(board[ctx->key_y]) - 1; - } - ctx->sel_dirty = true; - break; - - case PKB_RIGHT: - if (ctx->key_y == -1) { - if (ctx->cursor < strlen(ctx->content)) ctx->cursor ++; - } else if (ctx->key_y == 3 && ctx->key_x > 1 && ctx->key_x < 7) { - ctx->key_x = 7; - } else { - ctx->key_x ++; - ctx->key_x %= strlen(board[ctx->key_y]); - } - ctx->sel_dirty = true; - break; - - // Enter a character. - case PKB_CHARSELECT: - ctx->sel_dirty |= ctx->held != PKB_CHARSELECT; - if (ctx->key_y == 3) { - switch (ctx->key_x) { - case 0: - // Board selector. - if (ctx->board_sel == PKB_NUMBERS) ctx->board_sel = PKB_SYMBOLS; - else if (ctx->board_sel == PKB_SYMBOLS) ctx->board_sel = PKB_LOWERCASE; - else ctx->board_sel = PKB_NUMBERS; - ctx->kb_dirty = true; - break; - case 1: - // Magic. - pkb_append(ctx, *board[4]); - break; - default: - // Spacebar. - pkb_append(ctx, ' '); - break; - case 7: - // mAGIC. - pkb_append(ctx, *board[5]); - break; - case 8: - // Enter idk. - ctx->input_accepted = true; - break; - } - } else if (ctx->key_y == 2) { - if (ctx->key_x == 0) { - // cAPS LOCK KEY. - if (ctx->held == PKB_CHARSELECT) ctx->held = PKB_NO_INPUT; - ctx->board_sel ^= 1; - ctx->kb_dirty = true; - } else if (ctx->key_x == strlen(board[2])-1) { - // Backspace. - pkb_delete(ctx, true); - } else { - // nORMAL CHAR. - pkb_append(ctx, board[2][ctx->key_x]); - } - } else { - // Normal char. - pkb_append(ctx, board[ctx->key_y][ctx->key_x]); - } - break; - - // Shift key, the pressening. - case PKB_SHIFT: - ctx->board_sel |= 1; - ctx->kb_dirty = true; - break; - - // Next keyboard. - case PKB_MODESELECT: - ctx->board_sel ++; - ctx->board_sel %= 4; - rowlen = strlen(board[ctx->key_y]); - if (ctx->key_x >= rowlen) ctx->key_x = rowlen - 1; - ctx->kb_dirty = true; - break; - - // Backspace. - case PKB_DELETE_BEFORE: - pkb_delete(ctx, true); - break; - - // Delete. - case PKB_DELETE_AFTER: - pkb_delete(ctx, false); - break; - default: - break; - } - if (input != PKB_SHIFT && input != ctx->held) { - ctx->held = input; - ctx->hold_start = esp_timer_get_time(); - } - ctx->dirty = true; -} - -// A relealing of the input. -void pkb_release(pkb_ctx_t *ctx, pkb_input_t input) { - switch (input) { - // Shift key, the releasening. - case PKB_SHIFT: - ctx->dirty = true; - ctx->board_sel &= ~1; - ctx->kb_dirty = true; - break; - - // Unpress them char. - case PKB_CHARSELECT: - ctx->sel_dirty = true; - break; - - default: - break; - } - if (ctx->held == input) { - ctx->held = PKB_NO_INPUT; - ctx->dirty = true; - } -} diff --git a/main/uninstall.c b/main/uninstall.c index 08da592..11c0e43 100644 --- a/main/uninstall.c +++ b/main/uninstall.c @@ -27,6 +27,7 @@ typedef struct _uninstall_menu_args { void uninstall_browser(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) { menu_t* menu = menu_alloc("Uninstall application"); + const pax_font_t *font = pax_get_font("saira regular"); appfs_handle_t appfs_fd = APPFS_INVALID_FD; while (1) { @@ -49,7 +50,7 @@ void uninstall_browser(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* pax_background(pax_buffer, 0xFFFFFF); pax_noclip(pax_buffer); - pax_draw_text(pax_buffer, 0xFF000000, NULL, 18, 5, 240 - 19, "[A] uninstall app [B] back"); + pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 19, "[A] uninstall app [B] back"); bool quit = false;