Data: components 069-080

This commit is contained in:
ZacharyZhang-NY committed 2026-10-05 12:27:55 -04:00
1 parent 2a232930dd
commit 16533b8f02
71 files changed
+5400 -1

No files matched your search

+46
View File
@@ -0,0 +1,46 @@
# 069 Card · 卡片
## 用途
把一组相关内容放在带描边的表面上:标题、内容与页脚三个插槽。默认不增加点击行为;可选 `Decorated` 绘制宫廷风格的双线边框与四角菱形角饰。Card 是视觉回归基准之一,快照覆盖浅深主题与三种密度。
## 最小示例
```go
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.Card(c, mujica.CardOptions{Title: "Archive", Decorated: true, Footer: func() {
mujica.Button(c, "Open", mujica.ButtonOptions{})
}}, func() {
ui.Text(c, "Letters of the court, sealed in wax.")
}).Width(280)
}
ui.Render(view, 400, 300, 1)
```
## 参数
`func Card(c *ui.Context, opts CardOptions, body func()) *ui.Element`,`body` 构建内容插槽。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Title` | `string` | 空 | 衬线标题;为空时不显示标题区。同时作为分组的无障碍名称。 |
| `Footer` | `func()` | nil | 页脚插槽,位于分隔线下方并右对齐,常放操作按钮。 |
| `Decorated` | `bool` | false | 外框与内框双线、四角菱形与标题下菱形分隔线,均使用 Ornament 色。 |
## 状态
默认(Surface 表面 + Border 描边,4 DIP 圆角)、装饰(Ornament 双线与角饰)。卡片本身无悬停、按下、选中或禁用状态;内部控件保留各自状态。
## 事件
无。卡片不产生事件,交互来自内部控件。
## 键盘操作
卡片不获取焦点;Tab 按顺序进入内部控件。装饰只做绘制,不占焦点、不遮挡内容、不缩小点击区域。
## 限制
- 卡片不提供整卡点击;需要时由调用方在内容中放置按钮或链接。
- 角饰为矢量绘制,位于 4 DIP 内框的四角;装饰模式会额外增加 6 DIP 内边距。
+62
View File
@@ -0,0 +1,62 @@
# 070 List · 列表
## 用途
展示任意数量的条目,只构建可见行(加预取两行),10 万条记录也能流畅滚动、选择。支持列表与网格两种模式、单选与多选、稳定条目键、按标签输入定位,以及首次加载、追加加载、失败与空状态。
## 最小示例
```go
names := []string{"Matins", "Lauds", "Prime", "Terce"}
var state mujica.ListState[string]
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
v := mujica.List(c, &state, len(names), mujica.ListOptions[string]{
Key: func(i int) string { return names[i] },
Label: func(i int) string { return names[i] },
}, func(i int) { ui.Text(c, names[i]) })
v.Size(240, 200)
if v.Changed() {
key, _ := state.Selected()
fmt.Println("chose", key)
}
}
ui.Render(view, 400, 300, 1)
```
## 参数
`func List[K comparable](c *ui.Context, s *ListState[K], n int, opts ListOptions[K], item func(i int)) ListView`。`ListView` 嵌入 `*ui.Element`;`ListState` 由调用方持有,零值表示未选择。`state.Selected()` 返回所选键,多选时 `state.Selection` 保存全部键;`state.ScrollTo(i)` 滚动到第 i 项。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Key` | `func(i int) K` | 必填 | 条目的稳定键;选择与行状态跟随键,而不是下标。 |
| `Label` | `func(i int) string` | 必填 | 条目文字:无障碍名称与输入定位。 |
| `Multiple` | `bool` | false | 多选:Cmd/Ctrl 点击增减、Shift 连选、Cmd/Ctrl+A 全选。 |
| `Grid` | `bool` | false | 网格模式:按 `ItemWidth` 自动分列。 |
| `ItemWidth`, `ItemHeight` | `float32` | 160, 120 | 网格条目最小宽度与高度(DIP)。 |
| `Status` | `DataStatus` | `DataReady` | 加载状态:`DataLoading` 首次加载(无行时显示加载标记)、`DataLoadingMore` 追加加载(行下方显示“正在加载更多”)、`DataFailed` 失败(显示错误与“重试”)。 |
| `Error` | `string` | 内置“加载失败” | `DataFailed` 时显示的具体错误。 |
| `Empty` | `string` | 内置“暂无数据” | 无数据时的说明文字。 |
## 状态
默认、悬停(SurfaceHover)、选中(Accent 填充 + OnAccent 文字 + 勾选标记)、聚焦(列表外 2 DIP 焦点环)、网格选中(AccentText 边框 + 勾选)、加载、追加加载、失败、空。
## 事件
`ListView.Changed()`:选择变化;`Submitted()`:Enter 或双击;`Retried()`:点击失败状态的“重试”。
## 键盘操作
- ↑/↓、Home/End,Linux 与 Windows 上 PageUp/PageDown:移动选择;网格模式下方向键二维移动。
- 输入字母:按 `Label` 定位。
- Enter:提交。
- 多选:Shift+方向键连选;Cmd/Ctrl+A 全选;Linux/Windows 上 Ctrl+方向键只移动、Ctrl+Space 切换。
## 限制
- 虚拟化由 MyGo `ui.List`/`ui.GridView` 提供:每帧构建的元素数由可见区域和预取范围决定;程序跳转(`ScrollTo`)时目标两侧各构建一屏。测试以 10 万条记录统计“最后一帧调用条目构建函数的次数”验证上限(list_test.go)。
- MyGo 单选跟随键时只在原位置附近 1000 行内查找(ui/list.go:30 `listSearch`);插入或删除大量上方行后,单选可能被清除。
- Shift 连选的锚点由 MyGo 决定(ui/list.go `extend`),与平台习惯一致。
- 网格模式没有 `ListState.Visible` 等滚动位置读取接口。
+73
View File
@@ -0,0 +1,73 @@
# 071 DataTable · 数据表格
## 用途
按列展示数据行,只构建可见行。提供排序、筛选、多选、列宽、列顺序、列显隐与自定义单元格。行与列都以稳定 ID 保存状态:排序、筛选或调整列之后,选择仍指向同一条数据。默认使用本地排序与筛选(仅在数据、排序或筛选条件变化时计算一次并缓存);`Controlled` 模式下按调用方顺序显示,调用方在 `SortChanged()` 时自行查询。
## 最小示例
```go
type relic struct {
ID int
Name string
Age int
}
rows := []relic{{1, "Censer", 300}, {2, "Altar", 120}, {3, "Bell", 80}}
var state mujica.DataTableState[int]
opts := mujica.DataTableOptions[relic, int]{
Key: func(r relic) int { return r.ID },
Columns: []mujica.DataColumn[relic]{
{ID: "name", Title: "Name", Sortable: true,
Text: func(r relic) string { return r.Name },
Compare: func(a, b relic) int { return cmp.Compare(a.Name, b.Name) }},
{ID: "age", Title: "Age", Width: 80, Align: ui.End, Sortable: true,
Text: func(r relic) string { return strconv.Itoa(r.Age) },
Compare: func(a, b relic) int { return cmp.Compare(a.Age, b.Age) }},
},
}
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.DataTable(c, &state, rows, opts).Size(360, 240)
}
ui.Render(view, 400, 300, 1)
```
## 参数
`func DataTable[R any, K comparable](c *ui.Context, s *DataTableState[K], rows []R, opts DataTableOptions[R, K]) DataTableView`。另有 `DataTableColumnPicker(c, s, cols)`(“列”按钮与勾选弹层,控制显隐)和纯函数 `DataTableRows(rows, cols, sort, filter) []int`(本地排序筛选辅助,返回行下标)。
`DataTableState` 字段:`Sort ui.SortOrder`、`Filter string`(不区分大小写包含匹配全部列的 `Text`)、`Hidden map[string]bool`(按列 ID 隐藏)、`Layout ui.TableLayout`(用户拖动得到的列顺序与列宽,可保存恢复)、`Selection ui.Selection[K]`(多选)。方法:`Selected()`、`Rows()`(筛选后行数)。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Columns` | `[]DataColumn[R]` | 必填 | 列定义:`ID`(必填、唯一)、`Title`、`Width`(0 表示分配剩余宽度)、`MinWidth`、`Align`、`Sortable`、`Compare`(本地排序比较函数)、`Text`(必填,纯文本,用于筛选与默认单元格)、`Cell`(自定义单元格)。 |
| `Key` | `func(R) K` | 必填 | 行的稳定 ID;重复时 panic。 |
| `Multiple` | `bool` | false | 多选:首列显示勾选框,点击勾选框增减,Cmd/Ctrl、Shift 点击与 Cmd/Ctrl+A。 |
| `Controlled` | `bool` | false | 受控模式:不在本地排序筛选。 |
| `Version` | `int` | 0 | 原地修改 `rows` 后递增,通知缓存失效;换新切片无需递增。 |
| `Status` | `DataStatus` | `DataReady` | 加载状态:`DataLoading` 首次加载(无行时显示加载标记)、`DataLoadingMore` 追加加载(行下方显示“正在加载更多”)、`DataFailed` 失败(显示错误与“重试”)。 |
| `Error` | `string` | 内置“加载失败” | `DataFailed` 时显示的具体错误。 |
| `Empty` | `string` | 内置“暂无数据” | 无数据时的说明文字。 |
## 状态
默认、表头悬停、排序箭头(升/降)、行悬停、选中行(Accent 填充 + OnAccent 文字;单选首列菱形,多选首列勾选框)、聚焦(表格外焦点环)、加载、追加加载、失败、空、无匹配。数据行高度不低于当前密度的数据行高(28/36/44 DIP)。
## 事件
`Changed()`:选择变化;`Submitted()`:Enter 或双击;`SortChanged()`:点击表头改变了 `State.Sort`;`Retried()`:点击“重试”。
## 键盘操作
- ↑/↓、Home/End:移动选择;Enter:提交;输入字母按首个可见列定位。
- 多选:Shift/Cmd(Ctrl) 配合点击或方向键;Cmd/Ctrl+A 全选。
- 表头:点击排序、再次点击反向;拖动表头边缘调整列宽,双击适配内容;拖动表头移动列。
- 列选择器:Tab 进入勾选项,Space 切换;Escape 关闭。
## 限制
- MyGo `ui.Table` 只按调用方给出的顺序显示(docs/ui/table.md “Sorting”),因此本组件在本地完成排序,或在受控模式下交给调用方。
- 表头内容只能是 `Title` 文字(ui/table.go `table` 构建表头),无法放置全选勾选框;全选使用 Cmd/Ctrl+A。
- 单选的跟随由组件按键重新定位,跨越任意距离都有效;多选的键盘锚点在大规模重排后由 MyGo 重置(ui/list.go:30)。
- 删除的数据行对应的选择会在数据变化时清除;被筛选隐藏的行保留选择。
- 10 万行 × 10 列:测试统计“最后一帧构建过单元格的行数”不超过 16,并断言重复帧不再调用比较函数(data_table_test.go)。
+57
View File
@@ -0,0 +1,57 @@
# 072 Tree · 树
## 用途
展示层级数据:节点展开、选择、键盘导航、外部加载子项与空状态。只构建可见行,10 万节点同样流畅;折叠的子树不创建任何界面元素。
## 最小示例
```go
kids := map[string][]string{"Nave": {"Pulpit", "Pews"}}
var state mujica.TreeState[string]
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.Tree(c, &state, mujica.TreeOptions[string]{
Roots: []string{"Nave", "Sacristy"},
Children: func(n string) []string { return kids[n] },
Label: func(n string) string { return n },
}).Size(280, 240)
}
ui.Render(view, 400, 300, 1)
```
## 参数
`func Tree[K comparable](c *ui.Context, s *TreeState[K], opts TreeOptions[K]) TreeView`。节点值本身即稳定键。`TreeState` 方法:`Selected()`、`SetOpen(item, open)`、`IsOpen(item)`;字段 `Selection ui.Selection[K]` 保存多选。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Roots` | `[]K` | 空 | 顶层节点;为空时显示空状态。 |
| `Children` | `func(K) []K` | 必填 | 子节点:nil 表示叶子;未加载的节点返回空的非 nil 切片。 |
| `Label` | `func(K) string` | 必填 | 节点文字。 |
| `ItemStatus` | `func(K) DataStatus` | nil | 子项加载状态:`DataUnloaded`、`DataLoading`(行尾加载标记)、`DataFailed`(行尾错误与重试);nil 表示全部已加载。 |
| `Load` | `func(K)` | nil | 节点以 `DataUnloaded` 状态展开时调用一次,点击重试时再次调用。 |
| `Multiple` | `bool` | false | 多选。 |
| `Status` | `DataStatus` | `DataReady` | 加载状态:`DataLoading` 首次加载(无行时显示加载标记)、`DataLoadingMore` 追加加载(行下方显示“正在加载更多”)、`DataFailed` 失败(显示错误与“重试”)。 |
| `Error` | `string` | 内置“加载失败” | `DataFailed` 时显示的具体错误。 |
| `Empty` | `string` | 内置“暂无数据” | 无数据时的说明文字。 |
## 状态
默认、悬停、选中(Accent 填充 + 勾选标记)、聚焦、展开/折叠(箭头旋转)、子项加载中、子项加载失败、空、首次加载与失败。
## 事件
`Changed()`:选择变化;`Submitted()`:Enter 或双击;`Retried()`:整树失败时点击重试。子项重试直接调用 `Load`。
## 键盘操作
- ↑/↓:移动;→:展开或进入第一个子节点;←:折叠或回到父节点;macOS 上 Option、其他平台 Shift 配合 ←/→ 展开或折叠全部子孙。
- 输入字母按 `Label` 定位;Enter 提交。
## 限制
- 基于 MyGo `ui.Outline` 而不是 `ui.Tree`:`ui.Tree` 会构建全部已展开节点(docs/ui/tree.md “A tree builds every item it shows”),不满足大量节点虚拟化要求。
- `Outline` 每帧遍历已展开的节点以计算行(ui/outline.go `flatten`),元素数受可见区域限制,但遍历成本随展开节点数增长。
- 单选跟随节点的搜索范围为 1000 行(ui/list.go:30)。
- 异步加载由调用方在后台完成并通过 `Window.Update` 回到界面线程。
+61
View File
@@ -0,0 +1,61 @@
# 073 TreeTable · 树形表格
## 用途
把树形层级与表格列结合:首列显示展开箭头与缩进,其余列显示属性。支持展开、选择、列宽与列顺序、排序状态(同级节点在本地排序,结果按父节点缓存,只在子项或排序变化时重新计算),以及外部加载子项。只构建可见行。
## 最小示例
```go
kids := map[string][]string{"Vestry": {"Stole", "Alb"}}
size := map[string]int{"Vestry": 9, "Stole": 2, "Alb": 5, "Organ": 7}
var state mujica.TreeTableState[string]
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.TreeTable(c, &state, mujica.TreeTableOptions[string]{
Roots: []string{"Vestry", "Organ"},
Children: func(n string) []string { return kids[n] },
Label: func(n string) string { return n },
Columns: []mujica.TreeColumn[string]{
{ID: "name", Title: "Name", Cell: func(n string) { ui.Text(c, n) },
Compare: cmp.Compare[string]},
{ID: "size", Title: "Size", Width: 80, Align: ui.End,
Cell: func(n string) { ui.Text(c, strconv.Itoa(size[n])) }},
},
}).Size(360, 240)
}
ui.Render(view, 400, 300, 1)
```
## 参数
`func TreeTable[K comparable](c *ui.Context, s *TreeTableState[K], opts TreeTableOptions[K]) DataTableView`。`TreeTableState` 字段:`Sort`、`Layout`、`Selection`;方法:`Selected()`、`SetOpen`、`IsOpen`。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Columns` | `[]TreeColumn[K]` | 必填 | 列:`ID`(必填、唯一)、`Title`、`Width`、`MinWidth`、`Align`、`Compare`(设置后可点击排序同级节点)、`Cell`(必填)。首列在箭头后显示 `Cell`。 |
| `Roots` | `[]K` | 空 | 顶层节点。 |
| `Children` | `func(K) []K` | 必填 | 子节点:nil 为叶子,空切片为未加载。子项变化时请返回新切片(排序缓存按切片识别)。 |
| `Label` | `func(K) string` | 必填 | 无障碍名称与输入定位。 |
| `ItemStatus`, `Load` | | nil | 与 Tree 相同的外部加载协议。 |
| `Multiple` | `bool` | false | 多选。 |
| `Status` | `DataStatus` | `DataReady` | 加载状态:`DataLoading` 首次加载(无行时显示加载标记)、`DataLoadingMore` 追加加载(行下方显示“正在加载更多”)、`DataFailed` 失败(显示错误与“重试”)。 |
| `Error` | `string` | 内置“加载失败” | `DataFailed` 时显示的具体错误。 |
| `Empty` | `string` | 内置“暂无数据” | 无数据时的说明文字。 |
## 状态
默认、悬停、选中(Accent 填充 + 勾选标记)、聚焦、展开/折叠、排序箭头、子项加载中/失败、空。
## 事件
返回 `DataTableView`:`Changed()`、`Submitted()`、`SortChanged()`、`Retried()`。
## 键盘操作
- 与 Tree 相同的方向键与展开键;点击表头排序同级节点,再次点击反向;拖动表头边缘或表头调整列宽与顺序。
## 限制
- 基于 MyGo `ui.OutlineTable`;表头只能显示文字。
- 排序只作用于同级节点,层级关系保持不变。
+47
View File
@@ -0,0 +1,47 @@
# 074 Accordion · 手风琴
## 用途
多个可展开的区段放在一个带边框的盒子中。支持单项或多项展开、是否允许全部关闭,展开状态由调用方持有(受控)。
## 最小示例
```go
open := []string{"choir"}
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.Accordion(c, &open, []mujica.AccordionItem{
{ID: "choir", Title: "Choir", Content: func() { ui.Text(c, "Twelve voices.") }},
{ID: "nave", Title: "Nave", Content: func() { ui.Text(c, "Black oak pews.") }},
}, mujica.AccordionOptions{})
}
ui.Render(view, 400, 300, 1)
```
## 参数
`func Accordion(c *ui.Context, open *[]string, items []AccordionItem, opts AccordionOptions) AccordionView`。`*open` 是展开区段的 ID 列表;`AccordionItem` 字段:`ID`(必填、唯一)、`Title`、`Content`(必填)、`Disabled`。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Multiple` | `bool` | false | 允许同时展开多项;否则展开一项会关闭其他项。 |
| `KeepOne` | `bool` | false | 最后一个展开项不能被关闭。 |
## 状态
默认、悬停、聚焦、展开(箭头翻转,内容 120 ms 展开;减少动画时直接切换)、禁用(不展开,退出 Tab 序列)。
## 事件
`AccordionView.Changed()`:某区段因用户操作而展开或关闭,`*open` 已更新。外部直接修改 `*open` 不触发事件。
## 键盘操作
- Tab:到达标题;标题打开时 Tab 进入其内容。
- ↑/↓:上/下一个标题(跳过禁用项);Home/End:第一个/最后一个。
- Enter/Space:展开或关闭。
## 限制
- 基于 MyGo `ui.CollapsibleBase`;MyGo 的 `ui.Accordion` 外观固定且用内部状态移动焦点(ui/collapsible.go `accordionKeys`),因此键盘移动在组件内重新实现:向上移动时焦点在下一帧到达。
- 关闭动画进行的 120 ms 内内容仍在界面树中。
+45
View File
@@ -0,0 +1,45 @@
# 075 Collapsible · 折叠面板
## 用途
一个触发区控制下方内容的显示。展开状态由调用方的 `*bool` 控制,可在外部打开或关闭;关闭后的内容不构建,因此退出焦点序列。
## 最小示例
```go
open := false
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.Collapsible(c, &open, mujica.CollapsibleOptions{Title: "Details"}, func() {
ui.Text(c, "Candles are lit at the seventh bell.")
})
}
ui.Render(view, 400, 300, 1)
```
## 参数
`func Collapsible(c *ui.Context, open *bool, opts CollapsibleOptions, content func()) CollapsibleView`。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Title` | `string` | 空 | 触发区文字;与 `Trigger` 至少设置一个。 |
| `Trigger` | `func()` | nil | 自定义触发区内容(箭头之后)。 |
| `Disabled` | `bool` | false | 禁止展开或关闭,退出 Tab 序列。 |
## 状态
默认、悬停、按下、聚焦、展开(箭头旋转 90°,120 ms)、禁用。
## 事件
`CollapsibleView.Changed()`:用户点击或按键切换了展开状态。
## 键盘操作
- Enter/Space:展开或关闭。
- 关闭后内容不在 Tab 序列中。
## 限制
- MyGo `CollapsibleBase` 自带 200 ms 动画计时(ui/collapsible.go),组件使用自己的 120 ms 进度绘制,但 MyGo 的计时仍会在 200 ms 内请求帧。
+44
View File
@@ -0,0 +1,44 @@
# 076 Timeline · 时间线
## 用途
纵向列出事件:时间、标题、内容与状态。标记之间以细线连接,长内容自动换行。状态同时用形状、图标和文字表示,不只依赖颜色。
## 最小示例
```go
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.Timeline(c, []mujica.TimelineItem{
{Time: "06:00", Title: "Matins sung", Status: mujica.TimelineDone},
{Time: "09:00", Title: "Relics moved", Content: "From the crypt to the altar.", Status: mujica.TimelineActive},
{Time: "18:00", Title: "Vespers"},
})
}
ui.Render(view, 400, 300, 1)
```
## 参数
`func Timeline(c *ui.Context, items []TimelineItem) *ui.Element`。`TimelineItem` 字段:`Time`、`Title`、`Content`、`Status`。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Status` | `TimelineStatus` | `TimelineDefault` | `TimelineDefault`(空心菱形)、`TimelineDone`(勾选图标 + “已完成”)、`TimelineActive`(实心菱形 + “进行中”)、`TimelineWarning`(警告图标 + “警告”)、`TimelineError`(错误图标 + “错误”)。 |
## 状态
仅展示:默认、完成、进行中、警告、错误。
## 事件
无。
## 键盘操作
不获取焦点。
## 限制
- 仅纵向排列;内容为纯文本。
- 不虚拟化,适合几十条以内的事件。
+45
View File
@@ -0,0 +1,45 @@
# 077 DescriptionList · 描述列表
## 用途
以名称与值的形式展示详情,支持多列、跨列与复制值。容器宽度不足时自动减少列数,最窄时为单列。
## 最小示例
```go
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.DescriptionList(c, []mujica.DescriptionItem{
{Label: "Archivist", Value: "Sister Agnès", Copyable: true},
{Label: "Shelf", Value: "North vault, row 7"},
{Label: "Seal", Value: "Wine-red wax", Span: -1},
}, mujica.DescriptionListOptions{})
}
ui.Render(view, 400, 300, 1)
```
## 参数
`func DescriptionList(c *ui.Context, items []DescriptionItem, opts DescriptionListOptions) DescriptionListView`。`DescriptionItem` 字段:`Label`、`Value`、`Span`(跨列数,负数跨整行)、`Copyable`。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Columns` | `int` | 2 | 最多列数。 |
| `MinColumnWidth` | `float32` | 220 | 每列最小宽度(DIP);容器放不下时减少列数。 |
## 状态
默认、复制按钮悬停与聚焦、已复制(勾选图标 1.5 秒,并向读屏软件播报“已复制”)。
## 事件
`DescriptionListView.Copied()` 返回本帧被复制项的下标。
## 键盘操作
- Tab 到达每个复制按钮(名称为“复制 + 标签”),Enter/Space 复制。
## 限制
- 列数根据上一帧的宽度计算,宽度变化后在下一帧重新排列(组件会立即请求该帧)。
- 复制使用 MyGo 剪贴板接口,只写入纯文本。
+50
View File
@@ -0,0 +1,50 @@
# 078 Statistic · 统计数值
## 用途
突出显示一个数值,附带标题、单位、前后缀、精度与变化值说明。组件只格式化调用方给出的数值,不计算业务指标。
## 最小示例
```go
change := 12.5
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.Statistic(c, 12840, mujica.StatisticOptions{
Title: "Pilgrims", Unit: "souls", Precision: 0,
Change: &change, ChangeUnit: "%", ChangeNote: "vs last feast",
})
}
ui.Render(view, 400, 300, 1)
```
## 参数
`func Statistic(c *ui.Context, value float64, opts StatisticOptions) *ui.Element`。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Title` | `string` | 空 | 数值上方的标题。 |
| `Precision` | `int` | 0 | 小数位数;负数 panic。 |
| `Prefix`, `Suffix` | `string` | 空 | 紧贴数字的前后缀,如 `£`、`k`。 |
| `Unit` | `string` | 空 | 数字后的较小单位文字。 |
| `Format` | `func(float64) string` | 千分位分组 | 自定义数字格式。 |
| `Change` | `*float64` | nil | 变化值:正数显示上箭头与 Success 色,负数下箭头与 Danger 色,零为持平;同时带正负号。 |
| `ChangeUnit` | `string` | 空 | 变化值单位,如 `%`。 |
| `ChangeNote` | `string` | 空 | 变化值说明,如“较上次”。 |
## 状态
仅展示:上升、下降、持平(图标、符号与颜色共同表示)。
## 事件
无。
## 键盘操作
不获取焦点;分组名称把标题、数值、单位与变化一起读出。
## 限制
- 默认格式使用逗号分组与点号小数;其他地区格式通过 `Format` 提供。
+48
View File
@@ -0,0 +1,48 @@
# 079 ImageViewer · 图片查看器
## 用途
在窗口上方的模态层中查看图片:放大、缩小、平移、适应窗口、上一张/下一张,以及键盘操作与关闭。
## 最小示例
```go
picture := ui.MustParseSVG([]byte(`<svg xmlns="http://www.w3.org/2000/svg" width="240" height="160"><rect width="240" height="160" fill="#AD9164"/><path d="M120 20 L200 80 L120 140 L40 80 Z" fill="#7D2034"/></svg>`))
open, index := true, 0
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.ImageViewer(c, &open, &index, []mujica.ViewerImage{{Source: picture, Alt: "Rose window"}})
}
ui.Render(view, 400, 300, 1)
```
## 参数
`func ImageViewer(c *ui.Context, open *bool, index *int, images []ViewerImage) ImageViewerView`。`ViewerImage` 字段:`Source`(`*ui.Bitmap` 或 `*ui.SVG`,必填)、`Alt`(说明文字与无障碍名称)。关闭时返回的 `Element` 为 nil。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `open` | `*bool` | 必填 | 为 true 时显示;Escape、点击遮罩或关闭按钮设为 false。 |
| `index` | `*int` | 必填 | 当前图片下标;越界 panic。 |
| `images` | `[]ViewerImage` | 必填 | 至少一张。 |
## 状态
缩放 25%–800%(相对适应窗口),按钮在边界处禁用;适应窗口时“适应”按钮禁用;首张/末张时上一张/下一张禁用。
## 事件
`ImageViewerView.Changed()`:切换了图片,`*index` 已更新。关闭通过 `*open` 变为 false 观察。
## 键盘操作
- + / -:放大、缩小;0:适应窗口。
- ←/→:上一张、下一张;Shift+方向键:平移。
- 滚轮:缩放;拖动图片:平移。
- Escape:关闭;Tab 在工具按钮与图片之间移动。
## 限制
- 基于 MyGo `ui.DialogBase`,焦点限制与关闭后的焦点恢复由 MyGo 处理。
- 图片解码由调用方完成(`ui.DecodeBitmap`),组件不读取文件或网络。
- 不支持旋转与触控板捏合手势。
+49
View File
@@ -0,0 +1,49 @@
# 080 Carousel · 走马灯
## 用途
逐张展示内容,提供上一项、下一项与位置指示。默认不自动播放;开启自动播放后提供暂停按钮,并在指针悬停或焦点位于组件内时暂停。
## 最小示例
```go
index := 0
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.Carousel(c, &index, 3, mujica.CarouselOptions{Label: "Windows", Autoplay: true}, func(i int) {
ui.Text(c, fmt.Sprintf("Rose window %d", i+1)).Padding(24)
}).Size(360, 220)
}
ui.Render(view, 400, 300, 1)
```
## 参数
`func Carousel(c *ui.Context, index *int, n int, opts CarouselOptions, slide func(i int)) CarouselView`。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Label` | `string` | 空 | 无障碍名称。 |
| `Autoplay` | `bool` | false | 每隔 `Interval` 前进一项(循环)。 |
| `Interval` | `time.Duration` | 5s | 自动播放间隔;负数 panic。 |
| `Loop` | `bool` | false | 首尾相接;自动播放总是循环。 |
## 状态
默认、按钮悬停/按下/聚焦、首尾禁用(未循环时)、当前位置(实心菱形)、自动播放中、已暂停(显示继续按钮)。
## 事件
`CarouselView.Changed()`:当前项变化,`*index` 已更新;同时向读屏软件播报“第 N 项,共 M 项”。
## 键盘操作
- 焦点位于组件内时:←/→ 上一项、下一项;Home/End 第一项、最后一项。
- 位置指示为一个焦点组:方向键在指示点间移动,Enter/Space 跳转。
- Tab 依次到达上一项、下一项、位置指示与暂停按钮。
## 限制
- 切换不做滑动动画,直接显示新的一项。
- 不自动播放时没有计时器;自动播放只在可见帧中通过 `Context.After` 预约下一帧。
- `*index` 超出范围时会被夹到有效范围(记录 debug 日志),例如条目数减少后。