feat(Label): add label control #60

Merged
abart27 merged 5 commits from label-control into main 2026-03-15 12:52:47 +00:00
abart27 commented 2026-03-14 17:14:05 +00:00 (Migrated from github.com)

Adds a label control.

Pretty useless for now, but it will have selectability added in the future.

Closes #34

Adds a label control. Pretty useless for now, but it will have selectability added in the future. Closes #34
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2026-03-14 17:18:38 +00:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull request overview

Adds a new label control to the ugui control registry, wiring it into the build amalgamation and showcasing usage in an existing demo.

Changes:

  • Extend ControlType to include "label".
  • Add src/ugui/controls/label.lua implementing ugui.registry.label and the ugui.label() wrapper.
  • Register the new control file in build.py and add a demo usage.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/ugui/types.lua Adds "label" to the ControlType union.
src/ugui/controls/label.lua Introduces the label control registry entry and public placement function.
demos/overlapping_controls.lua Demonstrates placing a label control.
build.py Ensures the new control is included in the Lua amalgamation order.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

## Pull request overview Adds a new `label` control to the `ugui` control registry, wiring it into the build amalgamation and showcasing usage in an existing demo. **Changes:** - Extend `ControlType` to include `"label"`. - Add `src/ugui/controls/label.lua` implementing `ugui.registry.label` and the `ugui.label()` wrapper. - Register the new control file in `build.py` and add a demo usage. ### Reviewed changes Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments. | File | Description | | ---- | ----------- | | src/ugui/types.lua | Adds `"label"` to the `ControlType` union. | | src/ugui/controls/label.lua | Introduces the label control registry entry and public placement function. | | demos/overlapping_controls.lua | Demonstrates placing a label control. | | build.py | Ensures the new control is included in the Lua amalgamation order. | --- 💡 <a href="/mupen64/ugui/new/main?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.<br><br>You can also share your feedback on Copilot code review. [Take the survey](https://www.surveymonkey.com/r/XP6L3XJ).
@ -0,0 +1,50 @@
--
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-03-14 17:18:37 +00:00

The Label docs mention font_size/font_name fields, but the implementation never uses them (rendering always uses ugui.standard_styler.params.font_*). Either remove these fields from the API docs for now, or implement support (for example by mapping them into control.styler_mixin so they actually affect rendering).

The `Label` docs mention `font_size`/`font_name` fields, but the implementation never uses them (rendering always uses `ugui.standard_styler.params.font_*`). Either remove these fields from the API docs for now, or implement support (for example by mapping them into `control.styler_mixin` so they actually affect rendering).
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-03-14 17:18:37 +00:00

The docstring says ugui.label returns integer, Meta, but the registry logic always returns primary = nil, so the first return value is always nil. Please update the annotation to reflect the actual return type (e.g. nil, Meta).

The docstring says `ugui.label` returns `integer, Meta`, but the registry logic always returns `primary = nil`, so the first return value is always `nil`. Please update the annotation to reflect the actual return type (e.g. `nil, Meta`).
@ -0,0 +38,4 @@
draw = function(control)
local visual_state = ugui.get_visual_state(control)
ugui.standard_styler.draw_rich_text(control.rectangle, control.align_x, control.align_y, control.text, control.color, visual_state, control.plaintext, control.font_name, control.font_size)
end,
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-03-14 17:18:37 +00:00

draw_rich_text requires a non-nil color (BreitbandGraphics DrawTextParams.color is mandatory). Label.color is documented as optional, but control.color is passed through directly, so nil will likely error at runtime. Either make color required in validate, or provide a default (e.g. a standard styler text color for the current visual_state).

`draw_rich_text` requires a non-nil `color` (BreitbandGraphics `DrawTextParams.color` is mandatory). `Label.color` is documented as optional, but `control.color` is passed through directly, so `nil` will likely error at runtime. Either make `color` required in `validate`, or provide a default (e.g. a standard styler text color for the current `visual_state`).
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-03-14 17:18:37 +00:00

ControlType was extended with "label", but the codebase keeps control type definitions centralized in src/ugui/types.lua (e.g. Button, TextBox, ScrollBar, etc.). Label's ---@class was added inside controls/label.lua, which is inconsistent with the existing convention and makes types harder to discover. Consider moving the Label class annotation into types.lua alongside the other controls and keeping control files implementation-only.

`ControlType` was extended with `"label"`, but the codebase keeps control type definitions centralized in `src/ugui/types.lua` (e.g. `Button`, `TextBox`, `ScrollBar`, etc.). `Label`'s `---@class` was added inside `controls/label.lua`, which is inconsistent with the existing convention and makes types harder to discover. Consider moving the `Label` class annotation into `types.lua` alongside the other controls and keeping control files implementation-only.
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2026-03-15 11:58:46 +00:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull request overview

Adds a new Label control to ugui and extends rich-text rendering utilities to support per-call font overrides, laying groundwork for future selectable/copyable label text (Issue #34).

Changes:

  • Introduces a new ugui.label control and registers it in the control registry.
  • Updates standard_styler rich-text drawing/measurement to accept optional font_name/font_size.
  • Wires the new control into the amalgamation build and adds a demo usage.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/ugui/types.lua Extends ControlType union to include "label".
src/ugui/styler.lua Adds font override parameters to draw_rich_text/compute_rich_text.
src/ugui/controls/label.lua Implements the new label control and ugui.label(...) wrapper.
demos/overlapping_controls.lua Demonstrates label usage with custom font settings.
build.py Ensures the label control is included in the amalgamated build.
Comments suppressed due to low confidence (1)

src/ugui/styler.lua:327

  • In the plaintext branch, compute_rich_text returns segment_data as an object with segment/rectangle keys rather than an array of segment entries, which doesn't match the annotated return type and the non-plaintext branch. Returning a consistent array shape (e.g., one-element list) will avoid surprising consumers that iterate segment_data.
            return {
                segment_data = {
                    segment = {
                        type = 'text',
                        value = text,
                    },
                    rectangle = {
                        x = 0,

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

## Pull request overview Adds a new `Label` control to ugui and extends rich-text rendering utilities to support per-call font overrides, laying groundwork for future selectable/copyable label text (Issue #34). **Changes:** - Introduces a new `ugui.label` control and registers it in the control registry. - Updates `standard_styler` rich-text drawing/measurement to accept optional `font_name`/`font_size`. - Wires the new control into the amalgamation build and adds a demo usage. ### Reviewed changes Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments. <details> <summary>Show a summary per file</summary> | File | Description | | ---- | ----------- | | src/ugui/types.lua | Extends `ControlType` union to include `"label"`. | | src/ugui/styler.lua | Adds font override parameters to `draw_rich_text`/`compute_rich_text`. | | src/ugui/controls/label.lua | Implements the new label control and `ugui.label(...)` wrapper. | | demos/overlapping_controls.lua | Demonstrates label usage with custom font settings. | | build.py | Ensures the label control is included in the amalgamated build. | </details> <details> <summary>Comments suppressed due to low confidence (1)</summary> **src/ugui/styler.lua:327** * In the `plaintext` branch, `compute_rich_text` returns `segment_data` as an object with `segment`/`rectangle` keys rather than an array of segment entries, which doesn't match the annotated return type and the non-plaintext branch. Returning a consistent array shape (e.g., one-element list) will avoid surprising consumers that iterate `segment_data`. ``` return { segment_data = { segment = { type = 'text', value = text, }, rectangle = { x = 0, ``` </details> --- 💡 <a href="/mupen64/ugui/new/main?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.<br><br>You can also share your feedback on Copilot code review. [Take the survey](https://www.surveymonkey.com/r/XP6L3XJ).
@ -0,0 +11,4 @@
---@field public font_name string? The font family of the text. If `nil`, the default font family is used.
---@field public align_x Alignment? The text's horizontal alignment inside the control rectangle. If `nil`, `alignment.center` is assumed.
---@field public align_y Alignment? The text's vertical alignment inside the control rectangle. If `nil`, `alignment.center` is assumed.
---A label that contains text.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-03-15 11:58:45 +00:00

This repo centralizes control ---@class definitions in src/ugui/types.lua (e.g. Button/ToggleButton/TextBox/etc.). To keep tooling and docs consistent, consider adding the Label class definition there and avoiding defining control classes in individual control implementation files.

This repo centralizes control `---@class` definitions in `src/ugui/types.lua` (e.g. Button/ToggleButton/TextBox/etc.). To keep tooling and docs consistent, consider adding the `Label` class definition there and avoiding defining control classes in individual control implementation files.
@ -0,0 +37,4 @@
---@param control Label
draw = function(control)
local visual_state = ugui.get_visual_state(control)
ugui.standard_styler.draw_rich_text(control.rectangle, control.align_x, control.align_y, control.text, control.color, visual_state, control.plaintext, control.font_name, control.font_size)
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-03-15 11:58:45 +00:00

Label is documented as allowing color to be nil, but draw_rich_text ultimately passes the color into BreitbandGraphics.draw_text2, which calls brush_from_color(params.color) and will error on nil. Either make color required (and validate it), or provide a sensible default color (e.g. a new ugui.standard_styler.params.label.text[visual_state] or similar) when control.color is nil.

`Label` is documented as allowing `color` to be nil, but `draw_rich_text` ultimately passes the color into `BreitbandGraphics.draw_text2`, which calls `brush_from_color(params.color)` and will error on nil. Either make `color` required (and validate it), or provide a sensible default color (e.g. a new `ugui.standard_styler.params.label.text[visual_state]` or similar) when `control.color` is nil.
@ -0,0 +47,4 @@
ugui.label = function(control)
local result = ugui.control(control, 'label')
return result.primary, result.meta
end
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-03-15 11:58:46 +00:00

There is an established test suite for controls (see test/*.lua and test/runner.lua). Since this introduces a new public control (ugui.label), please add a test/label.lua group exercising at least validation and drawing codepaths (e.g., default alignments/font overrides) and register it in test/runner.lua so it runs in CI/local test runs.

There is an established test suite for controls (see `test/*.lua` and `test/runner.lua`). Since this introduces a new public control (`ugui.label`), please add a `test/label.lua` group exercising at least validation and drawing codepaths (e.g., default alignments/font overrides) and register it in `test/runner.lua` so it runs in CI/local test runs.
@ -311,3 +313,3 @@
compute_rich_text = function(text, plaintext)
compute_rich_text = function(text, plaintext, font_name, font_size)
if not text then
return {segment_data = {}, size = {x = 0, y = 0}}
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-03-15 11:58:46 +00:00

compute_rich_text now requires font_name/font_size but doesn't default them when callers omit the new args. There are existing call sites (e.g. TabControl sizing, tooltip sizing, and richtext tests) that call compute_rich_text(text, plaintext) / compute_rich_text(text); with the current implementation this will pass nil into BreitbandGraphics.get_text_size and can error. Consider making font_name/font_size optional and defaulting to ugui.standard_styler.params.* when nil to preserve backward compatibility.

`compute_rich_text` now requires `font_name`/`font_size` but doesn't default them when callers omit the new args. There are existing call sites (e.g. TabControl sizing, tooltip sizing, and richtext tests) that call `compute_rich_text(text, plaintext)` / `compute_rich_text(text)`; with the current implementation this will pass nil into `BreitbandGraphics.get_text_size` and can error. Consider making `font_name`/`font_size` optional and defaulting to `ugui.standard_styler.params.*` when nil to preserve backward compatibility.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-03-15 11:58:46 +00:00

ugui.internal.parse_rich_text returns an ordered array of segments, but this loop iterates it with pairs(segments), which does not guarantee traversal order. That can lead to rich text being measured/laid out out of order. Use ipairs(segments) here (and ipairs(segment_data) in the later aggregation loops) to keep ordering deterministic.

`ugui.internal.parse_rich_text` returns an ordered array of segments, but this loop iterates it with `pairs(segments)`, which does not guarantee traversal order. That can lead to rich text being measured/laid out out of order. Use `ipairs(segments)` here (and `ipairs(segment_data)` in the later aggregation loops) to keep ordering deterministic.
@ -138,3 +138,3 @@
---@alias ControlType "button" | "toggle_button" | "carrousel_button" | "textbox" | "joystick" | "trackbar" | "listbox" | "scrollbar" | "combobox" | "menu" | "numberbox"
---@alias ControlType "label" | "button" | "toggle_button" | "carrousel_button" | "textbox" | "joystick" | "trackbar" | "listbox" | "scrollbar" | "combobox" | "menu" | "numberbox"
---@alias ControlReturnValue { primary: any, meta: Meta }
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-03-15 11:58:46 +00:00

ControlType now includes "label", but there is no corresponding ---@class Label in src/ugui/types.lua alongside the other controls. Adding it there keeps the public type surface complete for users relying on the type annotations.

`ControlType` now includes "label", but there is no corresponding `---@class Label` in `src/ugui/types.lua` alongside the other controls. Adding it there keeps the public type surface complete for users relying on the type annotations.
Sign in to join this conversation.
No description provided.