apps: Store lists up to 40 apps, canvases fit the big screens, button:bg
- The catalog parse stopped at 16 rows and the catalog has 16, so a 17th app (Blackjack, #681) was silently never listed; installed apps had the same cap. Both are 40 now, and the catalog buffer grows from 8 KB to 24 KB so the JSON is not cut off. PSRAM only. - wada.ui.canvas raised a Lua error above 480 px, which killed apps that size a canvas from on_open(w, h) on the T-Display P4 (body ~575 tall), Tanmatsu and CrowPanel 5 (800 wide) (Discord). Sides are now clamped to the screen's long side instead. - button:bg(fill [, border]) colours a button (or boxes a label), so apps no longer fake coloured buttons from panels that keys cannot focus (Discord). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5198813f99
commit
9eda9b0f26
3 files changed
+36
-5
No files matched your search
@@ -261,17 +261,19 @@ return app</code></pre>
|
||||
<tr><td>wada.ui.clear()</td><td>Remove every widget from the app's page, leaving the page itself. This is how you build an app with more than one screen: clear, then create the next screen's widgets in the same place you built the first. <b>Any handle you still hold from before the clear is dead</b>: calling a method on it does nothing rather than crashing, but it will not come back, so re-create and re-assign. Older firmware has no <code>ui.clear</code>: write <code>local clear = ui.clear or function() end</code> if you need to run on both.</td></tr>
|
||||
<tr><td>wada.ui.list(x, y, w, h)</td><td>A scrollable list of selectable rows, the "pick one of N" widget. Methods: <code>add(text [, fn])</code> returning the row index, <code>set(i, text)</code>, <code>color(i, c)</code>, <code>select(i)</code> (highlights <i>and</i> scrolls it into view), <code>selected()</code>, <code>count()</code>, <code>clear()</code>, <code>pos(x, y)</code>. Rows are real buttons, so keyboard and trackball navigation walks them on touchless boards without you doing anything.</td></tr>
|
||||
<tr><td>wada.ui.input(title, initial, cb)</td><td>A modal text field. <code>cb(text)</code> on OK, <code>cb(nil)</code> on cancel or on the dialog being closed any other way: exactly one call, always, so an app that disabled itself while waiting always gets to re-enable. Uses the firmware's own dialog and keyboard, so it behaves identically on a touchscreen, on the Tanmatsu's physical keyboard and on a trackball board. One prompt at a time.</td></tr>
|
||||
<tr><td>wada.ui.canvas(w, h)</td><td>A drawing surface. See the canvas methods below.</td></tr>
|
||||
<tr><td>wada.ui.canvas(w, h)</td><td>A drawing surface. See the canvas methods below. Each side is clamped to the screen's long side (at least 480), so sizing it from <code>on_open(w, h)</code> is safe on every board.</td></tr>
|
||||
<tr><td>wada.ui.chart(points)</td><td>A line chart sized to the page. The Airtime and RF Monitor primitive.</td></tr>
|
||||
<tr><td>wada.ui.scroll(on)</td><td>Allow the page to scroll when content is taller than the screen.</td></tr>
|
||||
<tr><td>wada.ui.text_h(size)</td><td>Line height in pixels for a size class. Use it to lay out a canvas.</td></tr>
|
||||
<tr><td>wada.ui.colors</td><td>Theme table: <code>text</code>, <code>sub</code>, <code>bg</code>, <code>panel</code>, <code>accent</code>, <code>good</code>, <code>bad</code>, and on newer firmware <code>warn</code> (amber) and <code>border</code> (a panel's frame). Write <code>colors.warn or 0xE8A33D</code> to run on both.</td></tr>
|
||||
</table>
|
||||
<h3>Label handle</h3>
|
||||
<p>A button returns the same kind of handle, so all of these work on buttons too; <code>color</code> sets a button's text colour.</p>
|
||||
<table class="api">
|
||||
<tr><td>lbl:set(text)</td><td>Replace the text.</td></tr>
|
||||
<tr><td>lbl:color(c)</td><td>Set the colour, e.g. <code>wada.ui.colors.accent</code>.</td></tr>
|
||||
<tr><td>lbl:pos(x, y)</td><td>Place it explicitly instead of in flow.</td></tr>
|
||||
<tr><td>lbl:bg(fill [, border])</td><td>Fill colour behind it: on a button handle, the button's own colour (and its frame when <code>border</code> is given), so a coloured button stays a focus stop for the keys and trackball. New in beta_96: write <code>if b.bg then b:bg(c) end</code> to run on older firmware too.</td></tr>
|
||||
<tr><td>lbl:width(px, [align])</td><td>Fix the width; longer text wraps instead of running off the panel. Optional <code>"center"</code> / <code>"right"</code> aligns the text inside that width (default left).</td></tr>
|
||||
</table>
|
||||
<h3>Canvas handle</h3>
|
||||
|
||||
@@ -437,8 +437,17 @@ int cvGc(lua_State* L) {
|
||||
int uiCanvas(lua_State* L) {
|
||||
if (!s_h || !s_h->body) return luaL_error(L, "no app body");
|
||||
int w = (int)luaL_checkinteger(L, 1), h = (int)luaL_checkinteger(L, 2);
|
||||
luaL_argcheck(L, w > 0 && w <= 480, 1, "width 1..480");
|
||||
luaL_argcheck(L, h > 0 && h <= 480, 2, "height 1..480");
|
||||
luaL_argcheck(L, w > 0, 1, "width must be positive");
|
||||
luaL_argcheck(L, h > 0, 2, "height must be positive");
|
||||
// Up to the screen's long side (at least 480). A hard 480 made apps that size
|
||||
// a canvas from on_open(w, h) die with a Lua error on the larger screens:
|
||||
// the T-Display P4's body is ~575 tall, the Tanmatsu and CrowPanel 5 are 800
|
||||
// wide (Discord, Blackjack on the P4). Larger requests are clamped, not fatal.
|
||||
int lim = (int)lv_disp_get_hor_res(nullptr);
|
||||
if ((int)lv_disp_get_ver_res(nullptr) > lim) lim = (int)lv_disp_get_ver_res(nullptr);
|
||||
if (lim < 480) lim = 480;
|
||||
if (w > lim) w = lim;
|
||||
if (h > lim) h = lim;
|
||||
size_t bytes = (size_t)w * h * sizeof(lv_color_t);
|
||||
lv_color_t* buf = (lv_color_t*)heap_caps_malloc(bytes, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
if (!buf) return luaL_error(L, "canvas alloc failed");
|
||||
@@ -498,6 +507,23 @@ int lbColor(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// button:bg(fill [, border]) -- the fill colour of a button (or a label, which
|
||||
// then gets a solid box behind its text). Apps asked for coloured buttons and
|
||||
// were drawing their own from panels, which are no focus stop for keypad
|
||||
// navigation. Older firmware has no bg: `if b.bg then b:bg(c) end`.
|
||||
int lbBg(lua_State* L) {
|
||||
WidgetUd* u = checkLabel(L);
|
||||
if (!u->obj) return 0;
|
||||
lv_obj_set_style_bg_color(u->obj, lv_color_hex(argColor(L, 2)), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_opa(u->obj, LV_OPA_COVER, LV_PART_MAIN);
|
||||
if (!lua_isnoneornil(L, 3)) {
|
||||
lv_obj_set_style_border_color(u->obj, lv_color_hex(argColor(L, 3)), LV_PART_MAIN);
|
||||
if (lv_obj_get_style_border_width(u->obj, LV_PART_MAIN) == 0)
|
||||
lv_obj_set_style_border_width(u->obj, 1, LV_PART_MAIN);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lbWidth(lua_State* L) { // label:width(px [, "left"|"center"|"right"]) — wraps instead of overflowing
|
||||
WidgetUd* u = checkLabel(L);
|
||||
if (u->obj) {
|
||||
@@ -3068,6 +3094,7 @@ void openWada(lua_State* L) {
|
||||
lua_pushcfunction(L, lbPos); lua_setfield(L, -2, "pos");
|
||||
lua_pushcfunction(L, lbColor); lua_setfield(L, -2, "color");
|
||||
lua_pushcfunction(L, lbWidth); lua_setfield(L, -2, "width");
|
||||
lua_pushcfunction(L, lbBg); lua_setfield(L, -2, "bg");
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
@@ -33609,14 +33609,16 @@ struct LuaCatApp { char id[20]; char name[28]; char ver[12]; char desc[72]; cha
|
||||
// submission where a raw private-use codepoint would not be. Mapped to a glyph
|
||||
// by luaAppIconGlyph(); empty = the generic app symbol.
|
||||
struct LuaInstApp { char id[20]; char name[28]; char ver[12]; char icon[12]; };
|
||||
static const int kLuaCatMax = 16, kLuaInstMax = 16;
|
||||
// The catalog reached 16 apps in beta_95, and the parse loop stops at the cap,
|
||||
// so a 17th row (or install) was silently never listed. PSRAM only.
|
||||
static const int kLuaCatMax = 40, kLuaInstMax = 40;
|
||||
static const int kLangCatMax = LANG_COUNT + 2, kLangInstMax = LANG_COUNT;
|
||||
static LuaCatApp* s_lua_cat = nullptr; // PSRAM, allocated on first store use
|
||||
static int s_lua_cat_n = 0; // -1 = last fetch failed
|
||||
static LuaInstApp* s_lua_inst = nullptr; // PSRAM (see luaStoreTablesReady)
|
||||
static int s_lua_inst_n = 0;
|
||||
static char* s_luacat_buf = nullptr; // catalog JSON (PSRAM, worker-filled)
|
||||
static const size_t kLuaCatBufMax = 8192;
|
||||
static const size_t kLuaCatBufMax = 24576; // ~280 B per catalog row; PSRAM
|
||||
static volatile bool s_luacat_request = false, s_luacat_done = false;
|
||||
static volatile bool s_luainst_request = false, s_luainst_done = false;
|
||||
static bool s_luainst_ok = false;
|
||||
|
||||
Reference in new issue
Block a user