UI
Window methods use :; module functions such as ui.createWindow use .. Calls return true when admitted or nil, error unless a row states another result. Errors have operation = "ui", code, and message. Admission does not mean the Window has painted. Handles belong to the script runtime that created them and cannot be reused after reload. See Script-Created Windows for a complete input/action example and lifecycle behavior.
| API | Purpose | Important contract |
|---|---|---|
ui.createWindow(options) | Create a TaskManSync-owned Window | Returns handle or nil, error; title up to 1,024 UTF-8 bytes, integer width/height 160..4096 (defaults 400/240), visible defaults true |
ui.createRichText(html) | Construct rich-text input data | Returns a typed value or nil, error; bounded HTML, not TDML |
window:setTitle(title) | Set Window title | UTF-8 string up to 1,024 bytes |
window:setSize(width, height) | Change Window size | Integer dimensions 160..4096 |
window:show() | Show and activate | May recreate native realization |
window:hide() | Hide | Does not close the logical Window |
window:close() | Close | Closes current realization and records Window closure |
window:isVisible() | Read logical visibility | Boolean |
window:toggleVisibility() | Taskbar-style toggle | Show/activate, or hide when visible and active |
window:setContent(content) | Replace Window content | Atomic complete replacement |
window:getInput(id) | Read an input | Latest valid typed value; nil when no value, nil, error for an unknown input/invalid handle |
window:applyCellMutations(mutations) | Update Cell Space | Atomic batch, max 8,192 entries |
window:fullScreen() | Enter fullscreen | Command |
window:maximize() | Maximize | Command |
window:minimize() | Minimize | Command |
window:restore() | Restore normal presentation | Command |
window:raise() | Raise | Command |
window:activate() | Request activation | Command |
Settings/preview Windows validate calls but perform no native operations. Menus are not available to Scripted Decorations.
Content Values
window:setContent({ text = "...", inputs = {...}, actions = {...}, animated = false, visual = {...} }) replaces everything, including input values. Omitted collections become empty. Invalid fields, duplicate IDs, missing callback functions, or invalid values reject the whole replacement. text is a UTF-8 string, limited to 65,536 bytes, not taskbar TDML. Actions and inputs each have at most 16 entries. IDs are non-empty, at most 64 characters, and use ASCII letters, digits, _, or -. Labels are UTF-8 up to 1,024 bytes.
An action is { id = "apply", label = "Apply", enabled = true, callback = "applyValue" }. enabled defaults true; callback names an existing global function, not a function value. A complete example shows the callback reading form data. Required-input validation also applies to visual buttons.
The optional visual table has these fields:
| Field | Record or value | Limits and defaults |
|---|---|---|
background, fontFamily | Color string, font-family string | Colors up to 64 UTF-8 bytes; family up to 256 bytes |
items | { x=32, y=18, text="A", color="#39FF72", pixelSize=16, opacity=1, bold=false } | Up to 2,048; x/y -4096..4096, text 256 UTF-8 bytes each/65,536 total, integer size 1..256, opacity 0..1 |
lines | { x1=0, y1=0, x2=1, y2=1, color="#39FF72", width=2 } | Up to 2,048; endpoints 0..1, integer width 1..256, default 1 |
paths | Logical-pixel rectangle plus fill, stroke, strokeWidth, operations | Same shape and limits as Decoration paths |
cells | { column=20, row=10, character="@", foreground="#FFFFFF", background="#202020" } | Sparse; up to 8,192 retained cell records (not a grid dimension); unique integer coordinates, column and row each independently 1..4096 |
buttons | { id="apply", x=12, y=12, width=80, height=28, label="Apply", callback="applyValue", enabled=true } | Up to 16; x/y -4096..4096, dimensions 1..4096, IDs unique across buttons and actions |
Visual colors use Qt color syntax, including #RRGGBB and alpha-first #AARRGGBB, not TDML’s alpha-last eight-digit form. Visual buttons also accept optional color and labelColor; omitted label color uses automatic contrast. Their native hover/focus/disabled styling remains host-controlled. Positioned text is a UTF-8 string styled by its record fields, not TDML. Within the visual surface, layers are background, cells, lines, paths, text items, then buttons; ordinary text/inputs/actions are a separate layer above it. There is no per-primitive z-order or pointer-hit-test API.
Cell Space accepts exactly one printable Basic Latin character (U+0020..U+007E) or Halfwidth Forms character (U+FF61..U+FF9F) per record, not arbitrary Unicode, emoji, or combining/wide characters. Off-grid cells are clipped and may become visible when resized. Cell mutations are contiguous arrays of set, clear, or clearAll records. clearAll must be first and has no cell fields; addressed coordinates cannot repeat in a batch. The batch and retained collection are each limited to 8,192 entries. Mutations preserve other Window content, while complete content replacement replaces the cells.
animated = true delivers visible Window frame opportunities to onTick(frameTimeSeconds). onResize(windowId, dimensions) provides positive columns, rows, and surfaceAspect (visual width/height ratio), not pixel size, font metrics, or DPI. Initial dimensions arrive after realization; resize bursts coalesce, and hidden/minimized/preview Windows do not deliver them.
onKey(key, modifiers) receives key presses only for a focused visible Window. Keys are 0-9, A-Z, F1-F12, Escape, Enter, Space, Tab, Backspace, Delete, Insert, Left, Right, Up, Down, Home, End, PageUp, and PageDown. Modifiers are boolean shift, ctrl, alt, and meta. Fullscreen Escape is handled by the host before Lua. The callback does not receive a Window ID, key releases, repeat notifications, or text-composition events.
Window Inputs
Inputs share id, kind, optional label, optional value, and required (default false). An omitted value reads as nil; a supplied empty string or false is a valid value. An invalid edit retains the last valid value but prevents action activation if that input is required. Application policy, such as requiring a future alarm time, belongs in Lua. There is no general input-change callback; read values in an action or another callback using getInput().
kind | Accepted/returned value | Additional fields and behavior |
|---|---|---|
dateTime | time instant | Local-system date/time; optional components from year, month, day, hour, minute, second; hourFormat is "24" (default) or "12" |
duration | time duration | Non-negative; compare with a duration value, not a bare number |
boolean | Lua boolean | Checkbox; omitted required value is invalid even if displayed unchecked |
inputbox | UTF-8 string | Single line, up to 65,536 bytes |
number | Finite Lua number | -1000000000..1000000000; optional minimum/maximum narrow the inclusive range; not an integer-only input |
choice | Selected string identifier | Required options array with 1..64 unique { value="fast", label="Fast" } records; value must match an option |
editbox | UTF-8 string or rich-text value | Multiline; textFormat = "plainText" by default, or "richText"; serialized text up to 65,536 bytes |
calendar | time instant at local midnight | Date only; rejects non-midnight values and does not accept components or hourFormat |
For dateTime, omitted components are fixed rather than editable; an omitted second is fixed at zero. If components is absent, all six are available. Twelve-hour display changes only presentation; Lua still receives a normal instant. See Time for arithmetic and persistent millisecond conversion.
Rich-text editboxes require ui.createRichText(html), not a Lua string containing HTML. The returned value has :toHtml() and :toPlainText(). Persist the HTML string, then call createRichText when restoring; neither storage nor JSON accepts the rich-text value itself. This fragment installs a restored document in an existing Window:
local html = storage.getOrDefault("documentHtml", "<p>Initial <b>notes</b></p>")
local notes, richError = ui.createRichText(html)
if not notes then
log.error(richError.message)
return
end
function saveNotes()
local value, inputError = window:getInput("notes")
if not value then
if inputError then log.error(inputError.message) end
return
end
local accepted, err = storage.set("documentHtml", value:toHtml())
if not accepted then log.error(err.message) end
end
local ok, contentError = window:setContent({
inputs = {
{ id = "notes", kind = "editbox", textFormat = "richText", value = notes,
toolbar = {
{ id = "bold", label = "B", command = "bold" },
{ id = "bullets", label = "Bullets", command = "bulletList" },
} },
},
actions = { { id = "save", label = "Save", callback = "saveNotes" } },
})
if not ok then log.error(contentError.message) endThe example queues the save; use storage.flush before reporting durable success. HTML is the rich-text serialization format, not Markdown or taskbar TDML, and does not expose a native document object.
The optional formatting toolbar contains { id, label, command } records. Commands are bold, italic, underline, strikeout, textColor, paragraph, heading1, heading2, fontDecrease, fontIncrease, alignLeft, alignCenter, alignRight, bulletList, numberedList, outdent, and indent. They act on the current selection, or subsequent typing for character formatting; textColor opens a color picker. Each toolbar is limited to 16 records and is available only for rich-text editboxes.
topToolbar uses the same record shape for separator, save, cut, copy, paste, undo, redo, and spellCheck. A save record must have a matching normal Window action ID; it invokes that action rather than saving automatically. Spell-check availability depends on the host editor support. These controls do not provide arbitrary widgets, layouts, link dialogs, or QML access. The exported Rich Text Editor.lua demonstrates the complete editor and flush handling.