mirror of
https://github.com/badgeteam/mch2022-template-app.git
synced 2024-11-25 10:10:59 +00:00
Update UI fonts.
This commit is contained in:
parent
4960e10283
commit
872fd5da67
7 changed files with 16 additions and 944 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -37,3 +37,6 @@
|
||||||
[submodule "components/pax-codecs"]
|
[submodule "components/pax-codecs"]
|
||||||
path = components/pax-codecs
|
path = components/pax-codecs
|
||||||
url = https://github.com/robotman2412/pax-codecs.git
|
url = https://github.com/robotman2412/pax-codecs.git
|
||||||
|
[submodule "main/pax-keyboard"]
|
||||||
|
path = main/pax-keyboard
|
||||||
|
url = https://github.com/robotman2412/pax-keyboard
|
||||||
|
|
|
@ -4,7 +4,7 @@ idf_component_register(
|
||||||
"fpga_test.c"
|
"fpga_test.c"
|
||||||
"graphics_wrapper.c"
|
"graphics_wrapper.c"
|
||||||
"menu.c"
|
"menu.c"
|
||||||
"pax_keyboard.c"
|
"pax-keyboard/pax_keyboard.c"
|
||||||
"rp2040_updater.c"
|
"rp2040_updater.c"
|
||||||
"settings.c"
|
"settings.c"
|
||||||
"system_wrapper.c"
|
"system_wrapper.c"
|
||||||
|
@ -24,6 +24,7 @@ idf_component_register(
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
"include"
|
"include"
|
||||||
"menus"
|
"menus"
|
||||||
|
"pax-keyboard"
|
||||||
EMBED_TXTFILES ${project_dir}/resources/isrgrootx1.pem
|
EMBED_TXTFILES ${project_dir}/resources/isrgrootx1.pem
|
||||||
EMBED_FILES ${project_dir}/resources/wallpaper.png
|
EMBED_FILES ${project_dir}/resources/wallpaper.png
|
||||||
${project_dir}/resources/fpga_selftest.bin
|
${project_dir}/resources/fpga_selftest.bin
|
||||||
|
|
|
@ -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) {
|
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;
|
bool accepted = false;
|
||||||
pkb_ctx_t kb_ctx;
|
pkb_ctx_t kb_ctx;
|
||||||
pkb_init(pax_buffer, &kb_ctx, aOutput);
|
pkb_init(pax_buffer, &kb_ctx, 2048);
|
||||||
|
pkb_set_content(&kb_ctx, aOutput);
|
||||||
|
kb_ctx.kb_font = font;
|
||||||
|
kb_ctx.text_font = font;
|
||||||
|
|
||||||
pax_col_t fgColor = 0xFF000000;
|
pax_col_t fgColor = 0xFF000000;
|
||||||
pax_col_t bgColor = 0xFFFFFFFF;
|
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;
|
pax_col_t selColor = 0xff007fff;
|
||||||
|
|
||||||
kb_ctx.text_col = borderColor;
|
kb_ctx.text_col = borderColor;
|
||||||
kb_ctx.sel_text_col = selColor;
|
kb_ctx.sel_text_col = bgColor;
|
||||||
kb_ctx.sel_col = selColor;
|
kb_ctx.sel_col = selColor;
|
||||||
kb_ctx.bg_col = bgColor;
|
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_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_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_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_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);
|
pax_noclip(pax_buffer);
|
||||||
|
|
||||||
kb_ctx.x = aPosX + 1;
|
kb_ctx.x = aPosX + 1;
|
||||||
|
|
|
@ -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 <pax_gfx.h>
|
|
||||||
#include <pax_shapes.h>
|
|
||||||
#include <pax_fonts.h>
|
|
||||||
|
|
||||||
// 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
|
|
1
main/pax-keyboard
Submodule
1
main/pax-keyboard
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit ae075a054a640c33dd15494fda970ad42df1ce94
|
|
@ -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 <pax_keyboard.h>
|
|
||||||
#include <esp_timer.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
|
|
||||||
/* ==== 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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -27,6 +27,7 @@ typedef struct _uninstall_menu_args {
|
||||||
|
|
||||||
void uninstall_browser(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
void uninstall_browser(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
||||||
menu_t* menu = menu_alloc("Uninstall application");
|
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;
|
appfs_handle_t appfs_fd = APPFS_INVALID_FD;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -49,7 +50,7 @@ void uninstall_browser(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341*
|
||||||
|
|
||||||
pax_background(pax_buffer, 0xFFFFFF);
|
pax_background(pax_buffer, 0xFFFFFF);
|
||||||
pax_noclip(pax_buffer);
|
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;
|
bool quit = false;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue