feat(binarykeyboard): show fixed QWERTY layout with shaded halves

This commit is contained in:
2026-07-26 20:58:39 -04:00
parent 219795cc41
commit 7ba630a805
4 changed files with 52 additions and 21 deletions
+4 -2
View File
@@ -2,8 +2,10 @@
Proof of concept for entering text by recursively bisecting a QWERTY-ordered character set.
- Left side button selects the left group.
- Right side button selects the right group.
The full QWERTY layout stays in fixed positions. Remaining candidates are shaded by group; eliminated keys disappear.
- Up selects the plain (white) group.
- Down selects the shaded (dark) group.
- Back undoes one choice, or exits from the root.
- Confirm inserts a space.
- Left front button deletes a character.
+46 -17
View File
@@ -1,10 +1,15 @@
-- DESCRIPTION: Two-button recursive keyboard experiment
local KEYS = {
"Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",
"A", "S", "D", "F", "G", "H", "J", "K", "L",
"Z", "X", "C", "V", "B", "N", "M"
local ROWS = {
{ "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P" },
{ "A", "S", "D", "F", "G", "H", "J", "K", "L" },
{ "Z", "X", "C", "V", "B", "N", "M" }
}
local KEYS = {}
for _, row in ipairs(ROWS) do
for _, key in ipairs(row) do KEYS[#KEYS + 1] = key end
end
local MAX_TEXT_BYTES = 80
local text = ""
@@ -57,21 +62,47 @@ local function undo()
needsDraw = true
end
local function drawPanel(x, y, width, height, title, values)
gui.drawRoundedRect(x, y, width, height, 2, 8, COLOR_BLACK)
gui.drawText(FONT_UI_10, x + 12, y + 32, title, COLOR_BLACK, STYLE_BOLD)
gui.drawText(FONT_UI_12, x + 12, y + math.floor(height / 2), table.concat(values), COLOR_BLACK, STYLE_NORMAL)
-- Side Lookup - Rendering needs per-key shading, but candidates are stored in layout order.
local function sides()
local leftHalf, rightHalf = halves()
local result = {}
for _, key in ipairs(leftHalf) do result[key] = "left" end
for _, key in ipairs(rightHalf) do result[key] = "right" end
return result
end
local function drawKeyboard(width, top, bottom)
local gap = 6
local margin = 16
local keyWidth = math.floor((width - margin * 2 - gap * 9) / 10)
local keyHeight = math.min(56, math.floor((bottom - top - gap * 2) / 3))
local side = sides()
for rowIndex, row in ipairs(ROWS) do
local rowWidth = #row * keyWidth + (#row - 1) * gap
local startX = math.floor((width - rowWidth) / 2)
local y = top + (rowIndex - 1) * (keyHeight + gap)
for columnIndex, key in ipairs(row) do
local keySide = side[key]
if keySide then
local x = startX + (columnIndex - 1) * (keyWidth + gap)
local shaded = keySide == "right"
gui.fillRoundedRect(x, y, keyWidth, keyHeight, 4, shaded and COLOR_DARK_GRAY or COLOR_WHITE)
gui.drawRoundedRect(x, y, keyWidth, keyHeight, 1, 4, COLOR_BLACK)
local label = uppercase and key or key:lower()
local textX = x + math.floor((keyWidth - gui.getTextWidth(FONT_NOTOSANS_16, label, STYLE_BOLD)) / 2)
gui.drawText(FONT_NOTOSANS_16, textX, y + math.floor(keyHeight / 2) - 10, label,
shaded and COLOR_WHITE or COLOR_BLACK, STYLE_BOLD)
end
end
end
end
local function render()
local width = gui.width()
local height = gui.height()
local margin = 20
local gap = 12
local panelWidth = math.floor((width - margin * 2 - gap) / 2)
local panelTop = 185
local panelHeight = math.min(220, height - panelTop - 100)
local leftHalf, rightHalf = halves()
gui.clear()
gui.drawCenteredText(FONT_UI_12, 24, "Binary Keyboard", COLOR_BLACK, STYLE_BOLD)
@@ -79,10 +110,8 @@ local function render()
local visibleText = text == "" and "Type with the side buttons" or text:sub(-38)
gui.drawText(FONT_UI_12, margin + 12, 96, visibleText, COLOR_BLACK, STYLE_NORMAL)
local progress = string.rep("", #history)
gui.drawCenteredText(FONT_UI_10, 155, progress == "" and "Choose a half" or progress, COLOR_BLACK, STYLE_NORMAL)
drawPanel(margin, panelTop, panelWidth, panelHeight, "LEFT SIDE", leftHalf)
drawPanel(margin + panelWidth + gap, panelTop, panelWidth, panelHeight, "RIGHT SIDE", rightHalf)
gui.drawCenteredText(FONT_UI_10, 170, "UP = plain DOWN = shaded", COLOR_BLACK, STYLE_NORMAL)
drawKeyboard(width, 195, height - 90)
gui.drawButtonHints(#history == 0 and "Exit" or "Undo", "Space", "Delete", uppercase and "lower" or "UPPER")
gui.refresh(firstDraw and REFRESH_HALF or REFRESH_FAST)
+1 -1
View File
@@ -1,2 +1,2 @@
XTEINK-MANIFEST|1
main.lua|3720|8e275a05358e32b0187a7e2c00a93eabe658a32c10112c5451e2d8a78f3d3932
main.lua|4726|1a958ed089a1c3b6c8757298a94aed32fb2603732d83d3ed6c3ea98f31bd816a
+1 -1
View File
@@ -1,5 +1,5 @@
XTEINK-CATALOG|1
AppStore|Install apps from public Xteink repositories|apps/AppStore/manifest.txt|192|2eb608b92de6bdeff4fc8ed447b9319f45c0d79d5d73b14db1ab5a92f91e42d4
BinaryKeyboard|Two-button recursive keyboard experiment|apps/BinaryKeyboard/manifest.txt|97|b72b6250bb3124fb1639c9c1eb0c1b7730d62356189f450e26035dde288f9f2b
BinaryKeyboard|Two-button recursive keyboard experiment|apps/BinaryKeyboard/manifest.txt|97|8d26b7d2057f7ebdca133b936ea5d2074e8771af5235e9bf9722689a6fd8f5fd
HomeAssistant|Home Assistant status cards|apps/HomeAssistant/manifest.txt|177|b38ca49804444fd383a505ce9c51680ad9b7443950d682ca1b9ef3047bff98a5
Wordle|Guess the five-letter word in six tries|apps/Wordle/manifest.txt|177|199fafdf0d0f6e77916befc011f6e8466c254867800e1d4a9e67e95a06d0366b