jeopardy/gui/docs/gui-library-docs.md
2026-05-12 21:10:14 -07:00

1123 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# GUI Library Documentation
A LÖVE2D-based GUI framework with a dual-dimension layout system, event-driven architecture, theming, transitions, and a rich set of built-in widgets.
---
## Table of Contents
1. [Setup & Integration](#1-setup--integration)
2. [The Dual-Dimension Layout System](#2-the-dual-dimension-layout-system)
3. [Core Widget Reference](#3-core-widget-reference)
- [Frame](#31-frame)
- [TextLabel](#32-textlabel)
- [TextButton](#33-textbutton)
- [TextBox (Input)](#34-textbox-input)
- [ImageLabel](#35-imagelabel)
- [ImageButton](#36-imagebutton)
- [Video](#37-video)
4. [Base Object API](#4-base-object-api)
- [Positioning & Sizing](#41-positioning--sizing)
- [Appearance](#42-appearance)
- [Visibility & Lifecycle](#43-visibility--lifecycle)
- [Interaction](#44-interaction)
- [Shape & Form Factor](#45-shape--form-factor)
5. [Events & Connections](#5-events--connections)
- [Per-Object Events](#51-per-object-events)
- [Global Events](#52-global-events)
- [Hotkeys](#53-hotkeys)
6. [Theming](#6-theming)
7. [Color Module](#7-color-module)
8. [Transitions & Animation](#8-transitions--animation)
9. [Add-on Widgets](#9-add-on-widgets)
- [Window](#91-window)
- [ScrollFrame](#92-scrollframe)
- [Slide-in Menu](#93-slide-in-menu)
- [Video Player](#94-video-player)
10. [Canvas](#10-canvas)
11. [Simulation (Testing)](#11-simulation-testing)
12. [Scheduler Probe (Load Monitoring)](#12-scheduler-probe-load-monitoring)
13. [Task Manager](#13-task-manager)
14. [Tips & Patterns](#14-tips--patterns)
---
## 1. Setup & Integration
Require the library at the top of your project. The library hooks into LÖVE's callbacks automatically.
```lua
local gui = require("gui")
function love.update(dt)
gui.update(dt)
end
function love.draw()
gui.draw()
end
```
That is all that is required. The library installs its own hooks for `love.keypressed`, `love.mousepressed`, `love.resize`, etc., so you do not need to forward those manually.
### Creating Additional Processors
The library runs on the `multi` scheduler. If you need background work to integrate with the GUI update cycle, use `gui:newProcessor`:
```lua
local proc = gui:newProcessor("MyProcessor")
proc:newThread(function() ... end)
```
---
## 2. The Dual-Dimension Layout System
Every object's size and position is described by **eight numbers** that combine pixel offsets with fractional (01) scale values relative to the parent. This is the library's central concept.
```
setDualDim(x, y, w, h, sx, sy, sw, sh)
```
| Parameter | Meaning |
|-----------|---------|
| `x` | Pixel offset from parent's left edge |
| `y` | Pixel offset from parent's top edge |
| `w` | Pixel width |
| `h` | Pixel height |
| `sx` | Fractional X position (0 = left, 1 = right of parent) |
| `sy` | Fractional Y position (0 = top, 1 = bottom of parent) |
| `sw` | Fractional width (0 = 0px, 1 = full parent width) |
| `sh` | Fractional height (0 = 0px, 1 = full parent height) |
The resolved absolute values are calculated as:
```
absolute_x = parent.w * sx + x + parent.x
absolute_y = parent.h * sy + y + parent.y
absolute_w = parent.w * sw + w
absolute_h = parent.h * sh + h
```
### Examples
```lua
-- Full-screen frame (fills parent completely)
frame:setDualDim(0, 0, 0, 0, 0, 0, 1, 1)
-- Fixed 200×50 button in the top-left corner
btn:setDualDim(10, 10, 200, 50)
-- Centered horizontally, 300px wide, 5% from the top
panel:setDualDim(-150, 0, 300, 0, 0.5, 0.05, 0, 0.4)
-- sx=0.5 puts the left edge at the parent's midpoint;
-- x=-150 shifts it left by half the panel's own width.
-- Right-aligned sidebar, 20% of parent width, full height
sidebar:setDualDim(0, 0, 0, 0, 0.8, 0, 0.2, 1)
-- Anchored to bottom-right corner, fixed 100×30
btn:setDualDim(-110, -40, 100, 30, 1, 1)
```
### Helper: `fullFrame()`
Sets the object to fill its parent completely (equivalent to `setDualDim(0,0,0,0,0,0,1,1)`).
```lua
frame:fullFrame()
```
### Reading Position
```lua
local x, y, w, h = obj:getAbsolutes() -- resolved pixel values
local x, y, w, h, sx, sy, sw, sh = obj:getDualDim() -- raw dual-dim values
```
### Squaring
Setting `obj.square = "w"` forces `h = w` (width-driven square). Setting `obj.square = "h"` forces `w = h` (height-driven square). Useful for icon buttons and circle elements.
---
## 3. Core Widget Reference
All constructors follow the same signature pattern:
```lua
parent:newXxx(x, y, w, h, sx, sy, sw, sh)
```
where `parent` is either `gui` (the root) or another object. Children are drawn on top of and clipped by (if `clipDescendants` is set) their parent.
---
### 3.1 Frame
A plain rectangular container. The base building block.
```lua
local panel = gui:newFrame(x, y, w, h, sx, sy, sw, sh)
```
```lua
-- Example: a full-screen dark overlay
local overlay = gui:newFrame(0, 0, 0, 0, 0, 0, 1, 1)
overlay.color = {0, 0, 0}
overlay.visibility = 0.6
```
**Virtual Frame** — exists in memory and updates but is never drawn. Used to move objects off-screen without destroying them.
```lua
local vframe = gui:newVirtualFrame(...)
```
**Visual Frame** — a frame that does not participate in mouse hit-testing. Children of a visual frame are also non-interactive.
```lua
local display = gui:newVisualFrame(...)
```
---
### 3.2 TextLabel
A non-interactive frame that renders text.
```lua
local label = parent:newTextLabel("Hello, World!", x, y, w, h, sx, sy, sw, sh)
```
**Key properties:**
| Property | Type | Description |
|----------|------|-------------|
| `text` | string | The displayed text |
| `textColor` | color | Text color (default: black) |
| `font` | Font | LÖVE font object |
| `align` | constant | `gui.ALIGN_LEFT`, `gui.ALIGN_CENTER`, or `gui.ALIGN_RIGHT` |
| `textOffsetX/Y` | number | Pixel nudge for text rendering |
| `textScaleX/Y` | number | Scale multiplier for text |
| `textVisibility` | number | 01 alpha for text only |
**Font methods:**
```lua
label:setFont(16) -- set by size (default font)
label:setFont("fonts/myfont.ttf", 18) -- set by file + size
label:setFont(myLoveFont) -- set by existing font object
label:fitFont(minSize, maxSize) -- auto-fit text to the element's bounds
label:centerFont() -- vertically center text within element
```
---
### 3.3 TextButton
An interactive button with text. Automatically shows a hand cursor on hover.
```lua
local btn = parent:newTextButton("Click Me", x, y, w, h, sx, sy, sw, sh)
```
```lua
btn.OnReleased(function(self, x, y, button, istouch)
print("Button clicked!")
end)
```
Buttons automatically integrate with the theming system inside a `newWindow` — they receive button colors, hover highlights, and the button font.
---
### 3.4 TextBox (Input)
An editable single-line text input field. Gains focus on click and shows a blinking cursor.
```lua
local input = parent:newTextBox("placeholder", x, y, w, h, sx, sy, sw, sh)
```
**Key properties:**
| Property | Type | Description |
|----------|------|-------------|
| `text` | string | Current text value |
| `cur_pos` | number | Cursor position (character index) |
| `blink` | boolean | Whether cursor blinks (default: true) |
**Selection API:**
```lua
input:HasSelection() -- boolean
input:GetSelection() -- start, stop (always start <= stop)
input:GetSelectedText() -- string
input:ClearSelection()
```
**Events:**
```lua
input.OnReturn(function(self, text)
print("Submitted:", text)
end)
```
**Built-in hotkeys** (active when the textbox has focus):
- `Ctrl+A` — select all
- `Ctrl+C` — copy selection
- `Ctrl+V` — paste
- `Ctrl+X` — cut selection
- `Left/Right` — move cursor
- `Backspace/Delete` — delete character
---
### 3.5 ImageLabel
Displays an image. Supports PNG, JPG, and GIF.
```lua
local img = parent:newImageLabel("path/to/image.png", x, y, w, h, sx, sy, sw, sh)
```
The image is stretched to fill the element's bounds. GIFs animate automatically.
**Changing the image:**
```lua
img:setImage("path/to/other.png")
img:setImage(loveImageObject)
-- Tile from a spritesheet:
img:setImage("spritesheet.png", srcX, srcY, srcW, srcH)
```
**Flipping:**
```lua
img:flip() -- flip horizontally
img:flip(true) -- flip vertically
```
**Gradient fill** (applies a gradient image to any frame or image element):
```lua
panel:applyGradient("vertical", color1, color2, color3)
panel:applyGradient("horizontal", {1,0,0,1}, {0,0,1,1})
```
**Pre-loading images into cache:**
```lua
gui.cacheImage(gui, "assets/hero.png")
gui.cacheImage(gui, {"assets/a.png", "assets/b.png"})
```
---
### 3.6 ImageButton
An image that responds to click events. Shows a hand cursor on hover.
```lua
local btn = parent:newImageButton("icon.png", x, y, w, h, sx, sy, sw, sh)
btn.OnReleased(function(self)
self:setImage("icon_pressed.png")
end)
```
---
### 3.7 Video
Plays a LÖVE-supported video file inside an element.
```lua
local vid = parent:newVideo("movie.ogv", x, y, w, h, sx, sy, sw, sh)
```
**Playback control:**
```lua
vid:play()
vid:pause()
vid:stop() -- pause + rewind
vid:rewind()
vid:seek(t) -- seek to time in seconds
vid:tell() -- returns current time in seconds
vid:getDuration()
vid:setVolume(0.8)
```
**Events:**
```lua
vid.OnVideoFinished(function(self)
print("Video ended")
end)
```
---
## 4. Base Object API
Every object in the hierarchy inherits the following API.
---
### 4.1 Positioning & Sizing
```lua
obj:setDualDim(x, y, w, h, sx, sy, sw, sh) -- update position/size; nil preserves current value
obj:getAbsolutes() -- returns resolved x, y, w, h in pixels
obj:getDualDim() -- returns all 8 raw values
obj:move(dx, dy) -- increment pixel offset (fires OnPositionChanged)
obj:size(dx, dy) -- increment pixel size (fires OnSizeChanged)
obj:moveInBounds(dx, dy) -- move but keep within parent bounds
obj:fullFrame() -- shorthand for 100%×100% fill
obj:centerX(true) -- auto-center horizontally within parent
obj:centerY(true) -- auto-center vertically within parent
```
---
### 4.2 Appearance
```lua
obj.color = {r, g, b} -- background color (01 range)
obj.borderColor = {r, g, b} -- border color
obj.drawBorder = true/false -- show/hide border
obj.visibility = 0.8 -- overall opacity 01
obj.rotation = 45 -- rotation in degrees
obj:setRoundness(rx, ry, segments) -- round all corners
obj:setRoundness(rx, ry, seg, "top") -- round top corners only
obj:setRoundness(rx, ry, seg, "bottom") -- round bottom corners only
obj.shader = myShader -- apply a LÖVE shader (image elements only)
obj.clipDescendants = true -- clip child rendering to this element's bounds
```
---
### 4.3 Visibility & Lifecycle
```lua
obj.visible = false -- hide (and stop receiving events)
obj.active = false -- deactivate without hiding
obj:isActive() -- true if active and not in the virtual tree
obj:isOffScreen() -- true if fully outside the window
obj:topStack() -- move to top of parent's draw order (drawn last = on top)
obj:bottomStack() -- move to bottom of draw order
obj:destroy() -- remove from tree, disconnect all events, free resources
obj:removeChildren() -- destroy all children but keep the object itself
```
---
### 4.4 Interaction
```lua
-- Drag support
obj:enableDragging(gui.MOUSE_PRIMARY) -- enable drag with left mouse button
obj:enableDragging(gui.MOUSE_SECONDARY) -- enable drag with right button
obj:enableDragging(false) -- disable dragging
-- Hierarchy hit-testing: only fires events when not occluded by a sibling
obj:respectHierarchy(true)
-- Tag system (used for identifying objects and filtering events)
obj:tag("myTag") -- set the primary tag (accessible via :getTag())
obj:setTag("category") -- set an arbitrary tag key
obj:hasTag("category") -- boolean
obj:parentHasTag("visual") -- checks the ancestor chain
-- Tree queries
obj:getChildren() -- immediate children table
obj:getAllChildren() -- flat list of all visible descendants
obj:isDescendantOf(other) -- boolean
obj:canPress(mx, my) -- boolean: would a click at mx,my hit this object?
-- Cloning
local copy = obj:clone()
local copy = obj:clone({copyTo = parent, connections = true})
```
---
### 4.5 Shape & Form Factor
By default elements are rectangles. You can change an element's form factor:
```lua
-- Circle
obj:makeCircle(x, y, radius, sx, sy, sr, segments)
-- Arc
obj:makeArc(arcType, x, y, radius, sx, sy, sr, angle1, angle2, segments)
-- arcType is a LÖVE arc type string: "open", "closed", or "pie"
```
The `formFactor` property can also be set directly:
```lua
obj.formFactor = gui.FORM_RECTANGLE -- default
obj.formFactor = gui.FORM_CIRCLE
obj.formFactor = gui.FORM_ARC
```
---
## 5. Events & Connections
The library uses the `multi` connection system. Connections are called with the syntax:
```lua
obj.OnSomeEvent(function(self, ...)
-- handler
end)
```
Multiple handlers can be attached to a single event. Connections can be combined:
```lua
-- OR: fires the handler if either event fires
(obj.OnReleased + obj.OnReleasedOuter)(function() ... end)
-- AND: fires the handler only when both have fired
(conn1 * conn2)(function() ... end)
```
---
### 5.1 Per-Object Events
| Event | Arguments | Description |
|-------|-----------|-------------|
| `OnPressed` | `self, x, y, dx, dy, istouch` | Mouse pressed inside the element |
| `OnReleased` | `self, x, y, button, istouch, presses` | Mouse released inside the element |
| `OnReleasedOuter` | same | Released after a press, but outside the element |
| `OnReleasedOther` | same | Released with no previous press on this element |
| `OnPressedOuter` | `self, x, y, button, istouch, presses` | Pressed outside this element |
| `OnEnter` | `self, x, y` | Mouse moved onto the element |
| `OnExit` | `self, x, y` | Mouse moved off the element |
| `OnMoved` | `self, x, y, dx, dy, istouch` | Mouse moved while over the element |
| `OnDragStart` | `self, dx, dy, x, y, istouch` | Drag began |
| `OnDragging` | `self, dx, dy, x, y, istouch` | Drag in progress |
| `OnDragEnd` | `self, dx, dy, x, y, istouch, presses` | Drag ended |
| `OnWheelMoved` | `x, y` | Scroll wheel moved while cursor is over element |
| `OnSizeChanged` | `self, ...` | Element size changed |
| `OnPositionChanged` | `self, ...` | Element position changed |
| `OnDestroy` | `self` | Element is being destroyed |
| `OnCreated` | `element` | Fires for any descendant created under this element |
| `OnLoad` | — | Fires once when the element is first set up |
| `OnUpdate` | `self, dt` | Fires every update frame |
**Gamepad / joystick events** are also available on every object:
```lua
obj.OnLeftStickUp / Down / Left / Right
obj.OnRightStickUp / Down / Left / Right
```
**TextLabel / TextButton / TextBox extras:**
```lua
obj.OnFontUpdated(function(self) end) -- font changed
input.OnReturn(function(self, text) end) -- Enter key pressed in textbox
```
**Video extras:**
```lua
vid.OnVideoFinished(function(self) end)
```
---
### 5.2 Global Events
All global events live under `gui.Events`:
```lua
gui.Events.OnKeyPressed(function(key, scancode, isrepeat) end)
gui.Events.OnKeyReleased(function(key, scancode) end)
gui.Events.OnTextInputed(function(text) end)
gui.Events.OnMouseMoved(function(x, y, dx, dy, istouch) end)
gui.Events.OnMousePressed(function(x, y, button, istouch, presses) end)
gui.Events.OnMouseReleased(function(x, y, button, istouch, presses) end)
gui.Events.OnWheelMoved(function(x, y) end)
gui.Events.OnResized(function(w, h) end)
gui.Events.OnQuit(function() end)
gui.Events.OnFilesDropped(function(x, y, files) end)
gui.Events.OnFocus(function(focus) end)
gui.Events.OnObjectFocusChanged(function(previous, current) end)
-- Gamepad / joystick
gui.Events.OnGamepadPressed(function(joystick, button) end)
gui.Events.OnGamepadAxis(function(joystick, axis, value) end)
```
---
### 5.3 Hotkeys
Register a hotkey and get back a connection object:
```lua
local conn = obj:setHotKey({"lctrl", "s"})
conn(function(ref)
print("Save triggered from", ref)
end)
```
Multiple key combinations for the same action:
```lua
local onSave = gui:setHotKey({"lctrl", "s"}) + gui:setHotKey({"rctrl", "s"})
onSave(function() save() end)
```
**Built-in hotkeys:**
| Hotkey | Connection |
|--------|-----------|
| Ctrl+A | `gui.HotKeys.OnSelectAll` |
| Ctrl+C | `gui.HotKeys.OnCopy` |
| Ctrl+V | `gui.HotKeys.OnPaste` |
| Ctrl+X | `gui.HotKeys.OnCut` |
| Ctrl+Z | `gui.HotKeys.OnUndo` |
| Ctrl+Y / Ctrl+Shift+Z | `gui.HotKeys.OnRedo` |
| Ctrl+T | Toggle Task Manager |
---
## 6. Theming
The `theme` module generates consistent color palettes for use with `newWindow` and other themed widgets.
```lua
local theme = require("gui.core.theme")
```
### Creating a Theme
**From explicit colors:**
```lua
local t = theme:new(primaryColor, primaryText, buttonText, buttonNormal, primaryFont, buttonFont)
-- Using hex strings (most convenient):
local t = theme:new("#2d6a9f", "#f0f0f0", "#ffffff")
```
**From a table (preferred for full control):**
```lua
local t = theme:new({
primary = "#124559",
primaryDark = "#01161E",
primaryText = "#AEC3B0",
buttonNormal = "#1e6f8a",
buttonHighlight = "#2a9bbf",
buttonText = "#ffffff",
textFont = myFont,
buttonTextFont = myBoldFont,
-- Any extra keys are kept and accessible on the theme object
})
```
**Random harmonious theme:**
```lua
local t = theme:random() -- any brightness
local t = theme:random(nil, "dark") -- dark palette
local t = theme:random(nil, "light") -- light palette
local t = theme:random(12345) -- reproducible from a seed
print(t:getSeed()) -- retrieve the seed
print(t:dump()) -- export as hex string
```
### Theme Properties
| Property | Description |
|----------|-------------|
| `colorPrimary` | Main background color |
| `colorPrimaryDark` | Darker variant (headers, accents) |
| `colorPrimaryText` | Text on primary backgrounds |
| `colorButtonNormal` | Button resting color |
| `colorButtonHighlight` | Button hover color |
| `colorButtonText` | Text on buttons |
| `fontPrimary` | Font for labels |
| `fontButton` | Font for buttons |
### Applying a Theme to a Window
Pass the theme as the last argument to `newWindow` — the window will automatically style all child buttons and labels that are created inside it:
```lua
local win = gui:newWindow(x, y, w, h, "Title", draggable, myTheme)
```
---
## 7. Color Module
The `color` module handles color creation, conversion, and manipulation. All colors in the library are `{r, g, b}` or `{r, g, b, a}` tables with values in the 01 range.
```lua
local color = require("gui.core.color")
```
### Creating Colors
```lua
-- Hex string
color.new("#ff5500")
color.new("#ff550088") -- with alpha
-- CSS-style strings
color.new("rgb(255,85,0)")
color.new("rgba(255,85,0,0.5)")
color.new("hsl(20,100,50)")
color.new("hsla(20,100,50,0.8)")
-- Raw 01 floats
color.new(1, 0.33, 0)
-- HSL (hue 0360, sat 0100, light 0100)
color.new(color.hsl(200, 60, 40))
-- HSV (hue 0360, sat 01, val 01)
color.new(color.hsv(200, 0.6, 0.8))
```
### Manipulation
```lua
color.lighten(c, amount) -- amount is 01 factor
color.darken(c, amount)
color.saturate(c, amount)
color.desaturate(c, amount)
color.invert(c)
color.lerp(c1, c2, t) -- blend; t is 01
color.mix(c1, c2, t) -- alias for lerp
```
### Queries
```lua
color.isLight(c) -- boolean
color.getAverageLightness(c) -- 01 float
color.rgbToHex(c) -- returns hex string without "#"
```
### Arithmetic
Color objects support `+`, `-`, `*`, `/`, `%`, `^`, and unary `-` operators, applied component-wise.
### Named Colors
```lua
color.white
color.black
color.red
color.green
color.blue
color.highlighter_blue
-- (and more — check core_color.lua for the full list)
```
---
## 8. Transitions & Animation
The `transitions` module provides smooth interpolated animations for numeric values.
```lua
local transition = require("gui.elements.transitions")
```
### Built-in Transitions
Currently `transition.glide` is provided — a linear glide from a start value to a stop value.
### Using a Transition
A transition factory is created by calling `transition.glide(start, stop, duration)`. This returns a **factory function** that, when called, starts the animation and returns a handle.
```lua
-- Animate a panel sliding in from the left
local slideIn = transition.glide(-200, 0, 0.3) -- from -200 to 0 in 0.3 seconds
local t = slideIn() -- start the animation
t.OnStep(function(position)
panel:setDualDim(position)
end)
t.OnStop(function()
print("Animation complete")
end)
```
### Overriding Values at Runtime
The factory function accepts optional overrides:
```lua
local t = slideIn(newStart, newStop, newDuration)
```
### Stopping Early
```lua
t.Kill()
```
### Custom Transitions
```lua
local myTransition = transition:newTransition(function(t, start, stop, time)
-- t.fps is the target FPS for this transition
local steps = t.fps * time
local piece = time / steps
t.running = true
for i = 0, steps do
if not t.kill then
thread.sleep(piece)
-- push the current interpolated value as a status update
thread.pushStatus(start + i * ((stop - start) / steps))
end
end
t.running = false
t.kill = false
end)
```
### Changing FPS
```lua
transition.glide:SetFPS(30) -- lower for performance-sensitive animations
```
---
## 9. Add-on Widgets
These widgets live in `gui/addons` and extend the core library.
---
### 9.1 Window
A resizable, draggable floating window with a title bar and a close button.
```lua
require("gui.addons") -- loads addons
local win = gui:newWindow(x, y, width, height, "Window Title", draggable, theme)
```
The returned object is the **inner content frame** (inside the title bar). Add children directly to `win`.
**API:**
```lua
win:setTitle("New Title")
win:close() -- moves the window to the virtual tree (hides it)
win:open() -- brings the window back to the main tree
win:setTheme(theme) -- re-apply a different theme
win:getTheme() -- returns current theme
win.OnClose(function(self)
-- fires when the X button is pressed
end)
```
**Minimum dimensions:** 200px wide, 100px tall (enforced by resize handles).
**Children auto-styled:** Any `TYPE_BUTTON` or `TYPE_TEXT` created inside the window automatically receives the theme's colors and fonts via the `OnCreated` event.
---
### 9.2 ScrollFrame
A viewport with automatic vertical and horizontal scrollbars. Returns the **content frame** — add children to that.
```lua
require("gui.addons")
local content = gui:newScrollFrame(x, y, w, h, sx, sy, sw, sh)
-- Add children to `content`:
local row = content:newFrame(0, rowY, 0, 30, 0, 0, 1)
```
**Scrolling API (on the content frame):**
```lua
content:scrollTo(scrollY, scrollX) -- jump to absolute scroll position
content:scrollBy(deltaY, deltaX) -- scroll by a relative amount
content:scrollToTop()
content:scrollToBottom()
content:setScrollSpeed(speed) -- default is 40 pixels per wheel tick
content:getScrollPos() -- returns scrollX, scrollY
content:getMaxScroll() -- returns maxScrollX, maxScrollY
content:setContentSize(width, height) -- explicitly set the content dimensions
```
The scrollbars appear automatically when the content overflows the viewport and hide when it does not.
---
### 9.3 Slide-in Menu
A panel that slides in from the left, right, or top with an animated transition.
```lua
local transition = require("gui.elements.transitions")
local menu = gui:newMenu(title, size, position, trans)
-- title : string label (required)
-- size : fractional width/height (e.g. 0.25 for 25% of screen)
-- position : gui.ALIGN_LEFT (default), gui.ALIGN_RIGHT, or gui.ALIGN_CENTER
-- trans : transition factory (default: transition.glide)
```
**API:**
```lua
menu:Open(true) -- slide open
menu:Open(false) -- slide closed
menu:isOpen() -- boolean
```
**Example:**
```lua
local sidebar = gui:newMenu("Navigation", 0.2, gui.ALIGN_LEFT)
-- Add content to the menu frame
local navBtn = sidebar:newTextButton("Home", 10, 60, 180, 40)
-- Wire toggle
toggleBtn.OnReleased(function()
sidebar:Open(not sidebar:isOpen())
end)
```
---
### 9.4 Video Player
A pre-built media player widget with play/pause toggle and a seek bar.
```lua
require("gui.addons")
gui:newVideoPlayer(source, x, y, w, h, sx, sy, sw, sh)
```
The player creates its own themed window containing the video, a play/pause button, and a progress bar.
---
## 10. Canvas
The `canvas` module creates full-screen root frames.
```lua
local newCanvas = require("gui.core.canvas")
local visual = newCanvas("visual") -- visual frame: non-interactive, for backgrounds/effects
local regular = newCanvas() -- regular interactive frame
```
**Swapping child trees between canvases:**
```lua
visual:swap(frameA, frameB)
-- Exchanges the children of frameA and frameB, re-parenting correctly.
-- Useful for scene transitions.
```
---
## 11. Simulation (Testing)
The `simulate` module lets you programmatically fire mouse events, useful for automated testing or scripted UI demos.
```lua
local simulate = require("gui.core.simulate")
```
### Methods
```lua
-- Immediate (synchronous) mouse press and release
simulate:Press(button, x, y, istouch)
simulate:Release(button, x, y, istouch)
-- Async click (press then release after one scheduler tick)
simulate.Click(obj, button, x, y, istouch)
-- Animated mouse movement
simulate.Move(obj, dx, dy, x, y, istouch)
```
When called on an object (`obj:Press()`), the position defaults to the object's center. When called on `simulate` directly, `x` and `y` default to the current mouse position.
**Example:**
```lua
-- Programmatically click a button
simulate.Click(myButton)
-- Simulate a drag from one point to another
simulate.Move(nil, 100, 0, startX, startY) -- move 100px to the right
```
---
## 12. Scheduler Probe (Load Monitoring)
Measures scheduler responsiveness using tick-slip detection. Gives a 0100% load estimate without blocking.
```lua
local probe = require("gui.core.probe")
probe:install(multi)
```
**Options:**
```lua
probe:install(multi, {
interval = 0.05, -- probe fires every N seconds (default: 0.05)
alpha = 0.15, -- EMA smoothing factor 01 (default: 0.15, lower = smoother)
maxLag = 0.5, -- seconds of lag that equals 100% load (default: 0.5)
})
```
**Reading load:**
```lua
-- Both are non-blocking — safe to call every frame
local load, lagMs = multi:getLoad()
-- load : integer 0100
-- lagMs : smoothed scheduler lag in milliseconds
local lagMs, lagRatio = multi:getSchedulerLag()
```
The probe is automatically installed when `gui:showTaskManager()` is called.
---
## 13. Task Manager
A built-in debug overlay showing all active scheduler tasks, their state, uptime, and priority.
```lua
require("gui.addons")
gui:showTaskManager()
```
**Default hotkey:** `Ctrl+T` toggles it open/closed.
The task manager window provides:
- A list of all processors, threads, and tasks with live state
- Pause/Resume buttons for individual tasks
- Kill buttons to terminate tasks
- Clickable priority column to cycle a task's scheduler priority
- An Error Log tab that captures all thread errors in real-time
- A load bar showing current scheduler utilization
---
## 14. Tips & Patterns
### Aspect Ratio Locking
```lua
-- Lock the root to a 16:9 canvas; letterbox on resize
gui:setAspectSize(1920, 1080)
gui.aspect_ratio = true
```
### Clipping Children
```lua
local container = gui:newFrame(x, y, w, h)
container.clipDescendants = true -- children are scissored to container bounds
```
### Tag-Based Queries
```lua
-- Mark a group of elements and query by tag
for _, child in ipairs(parent:getAllChildren()) do
if child:hasTag("card") then
child.color = selectedColor
end
end
```
### Using `gui.apply` for Bulk Property Setting
`gui.apply` sets properties on multiple objects at once. It understands connection names (`C_` prefix), invoke-style functions (`I_` prefix), and plain properties.
```lua
gui.apply({
color = {0.2, 0.2, 0.2},
drawBorder = false,
I_enableDragging = {gui.MOUSE_PRIMARY},
OnReleased = function(self) print("clicked", self:getTag()) end,
}, btn1, btn2, btn3)
```
### Stacking Order
Objects are drawn in the order they appear in their parent's `children` table. The last child is drawn on top.
```lua
obj:topStack() -- draw on top of siblings
obj:bottomStack() -- draw below all siblings
```
### Responsive Layouts
Combine fractional scale with negative pixel offsets for padding:
```lua
-- A frame inset 10px on all sides within its parent
inner:setDualDim(10, 10, -20, -20, 0, 0, 1, 1)
```
### Intersection Testing
```lua
local ix, iy, iw, ih = obj:intersecpt(x, y, w, h)
-- Returns the overlapping rectangle, or 0,0,0,0 if no overlap
```
### Programmatic Focus
```lua
local focused = gui:getObjectFocus() -- the currently focused object
```
### OnUpdate (per-frame callback)
```lua
obj:OnUpdate(function(self, dt)
-- runs every frame while the object exists
self.rotation = self.rotation + 90 * dt
end)
```