展示HN:面向Ada的现代GUI库——CSS样式、XML界面与SDL3
摘要
Adi2是一个面向Ada的现代GUI库,提供CSS样式、基于XML的UI布局,并在SDL3上实现丰富内容渲染,同时支持WebAssembly和工具特性。
查看缓存全文
缓存时间: 2026/08/24 16:49
ovenpasta/adi2 来源: https://github.com/ovenpasta/adi2
Adi2
一个用于 Ada 的现代 GUI 库。
Adi2 为您提供一个真正的控件工具包,具备开发者期望从现代 UI 技术栈中获得的所有特性:类似 CSS 的样式支持(支持实时重载)、声明式 XML 布局、动画效果、SVG 与 Lottie 图形、国际化以及资源打包——所有这些功能均基于 SDL3 以原生 Ada 代码实现。
现状: 已在生产环境中使用,但尚未发布稳定版本——不同版本间的 API 可能会发生变更。
为什么选择 Adi2?
- 像 Web 一样为 UI 设置样式。 选择器、伪类、部件、过渡效果、渐变、盒阴影——全部使用熟悉的
.css语法。编辑文件,保存,即可看到变更。开发过程中无需重新编译。更喜欢纯 Ada 代码?CSS 规则本质上就是Style_Rules的 Ada 聚合体——可以完全手写,无需额外步骤(参见下方代码片段)。 - 以声明方式描述 UI——或者不采用声明方式。 在 XML 中编写
<button>、<stack>、<label>等标签,让工具链生成清晰的 Ada 包,或者在 Ada 中通过基于句柄的构建器直接构造相同的控件树。两种方式最终都调用完全相同的 API;XML 生成器只是一种便利工具,而非必需品。 - 渲染丰富内容。 内置的轻量级 HTML 视图控件可以渲染文档风格的标记语言,并支持级联样式。通过 SDL3_image 处理位图图像,通过内置的 plutosvg 处理 SVG,通过内置的 rlottie 处理 Lottie 动画。
- 分发单个二进制文件。 将所有 CSS 文件、字体、图片、翻译文件和 SVG 精灵图打包进您的可执行文件中。运行时无需文件系统依赖。
- 使用用户的语言。 兼容 Gettext 的国际化方案,支持复数形式、自动区域检测以及
.po→ Ada 的编译。 - 无需样板代码即可实现动画。 支持对
color、background-color、border-color、border-width、border-radius、padding、margin、opacity、box-shadow和font-size进行 CSS 过渡——框架自动处理插值和计时。 - 适配高 DPI 设备的单位。 布局使用
dp/dip,排版使用rem,当需要精确表示一个渲染像素时使用pix,而px——根据是否调用Set_Px_Maps_To_Dip来决定是否跟随显示缩放比例。详见docs/css_styling.md。 - 为工具链和自动化构建。 一个仅在开发阶段可用的 MCP 桥接器,允许编辑器和 AI 助手截取运行应用的屏幕截图、遍历控件树,并操控它——点击按钮、在输入框中输入内容、移动焦点、读取性能计数器。非常适合您选择的 AI 来编写端到端测试。
- 可在浏览器中运行。 示例代码可通过 GNAT-LLVM 和 Emscripten 编译为 WebAssembly——在线体验 (https://pizzahack.eu/adi2/demo/),或查看
wasm/目录了解构建方式。
发布所需的成本
一个发布版本会将所有内容静态链接成一个不到 10 MB 的单一可执行文件——控件工具包、CSS 引擎、SVG 和 Lottie 渲染,全部包含在内。您打包的任何资源都会在此基础上增加其体积。它通过 SDL 的渲染器进行绘制,该渲染器绑定到宿主系统提供的任何图形 API:在 Windows 上是 Direct3D,在 macOS 上是 Metal,在支持的地方使用 Vulkan 或 OpenGL,软件渲染作为兜底方案。Windows XP 使用 Direct3D 9,而当前 Mac 使用 Metal,均来自相同的源代码。
| Adi2 | Qt | Flutter | Electron | |
|---|---|---|---|---|
| 发布大小 | <10 MB,单文件 | ~15–30 MB 静态链接;否则需要随附一个 Qt 运行时 | ~20 MB+,引擎加数据目录 | ~100 MB+,捆绑 Chromium 和 Node |
| 运行时 | 自包含 | Qt 库和插件 | Flutter 引擎;在 Linux 上为 GTK3 | Chromium 和 Node |
| 图形 | SDL 渲染器,包含软件后备 | GPU 或光栅化后端 | Skia 或 Impeller,需要 GPU | GPU 栈和合成器 |
| 可移植性 | Windows XP+,macOS,Linux,WebAssembly | Windows 10+,macOS,Linux,移动端,嵌入式 | Windows 10+,macOS,Linux,移动端,Web | Windows 10+,macOS,Linux |
| 语言 | Ada | C++ | Dart | JavaScript |
| 内存安全 | 已检查,确定性回收 | 手动管理 | 垃圾回收 | 垃圾回收 |
| 样式 | CSS | QSS | Dart 控件代码 | CSS |
尺寸数据基于最小应用;您的应用会因自身代码和资源而增长。其他选项的体积换来了庞大的生态系统和多年的生产实践——Adi2 提供的权衡是,您只需交付一个单一文件,即使在那些已被其他工具放弃的硬件上也能运行。
截图
hello_example
hello_example
material_demo
material_demo
html_view_example
html_view_example
rlottie_example
rlottie_example
assets_example
assets_example
所有示例的完整截图集:docs/gallery.md。或在浏览器中自行运行:在线演示 (https://pizzahack.eu/adi2/demo/)。
快速体验
声明式路径 — XML + CSS
/* examples/css/hello_example.css */
.primary {
background-color: rgb(37, 99, 235);
border-radius: 8px;
padding: 10px 16px;
transition: background-color 150ms ease-out;
}
.primary:hover {
background-color: rgb(29, 78, 216);
}
.primary::label {
color: white;
font-size: 14px;
font-weight: 500;
}
<stack>
<button class="primary">
<label>Hello, world!</label>
</button>
</stack>
工具链会生成一个类型化的 Ada 包,您可以在 main 中实例化它——完整的约 25 行程序请参见 examples/hello_example.adb。
同样的事情,使用 Ada 手写实现
上面的 CSS 规则只是一个聚合体。XML 控件树也只是几个构造器调用。两种方式最终都使用相同的 API——完整的等效程序请参见 examples/hello_raw_example.adb。样式代码的结构如下:
function Style return Style_Builder renames Adi.Widget_Styles.Create;
-- 相当于 hello_example.css 中的 .primary 基础样式 + :hover 状态
Primary_Base : constant Style_Rules := (
Background_Color => Set_Bg (RGB (37, 99, 235)),
Border_Radius => Set (Radius (Px (8.0))),
Padding => Set (CSS_Box (Px (10.0), Px (16.0))),
Transition => Set ((Duration => 0.15, Easing => Ease_Out,
Properties => Props (Prop_Background_Color))),
others => <>
);
Primary_Hover : constant Style_Rules := (
Background_Color => Set_Bg (RGB (29, 78, 216)),
others => <>
);
-- 将基础样式和悬停样式绑定到按钮的 Main_Part
Set_Part_Style (Widget_Handle'(+Btn), Main_Part,
Style.Base (Primary_Base).On_Hover (Primary_Hover).Build);
构建并运行任一版本:
tools/build_examples.sh hello_example hello_raw_example
./examples/bin/hello_example # XML + CSS 流水线
./examples/bin/hello_raw_example # 纯手写 Ada
快速开始
# 构建库
alr build -- -j0
# 构建并运行测试套件
tools/run_tests.sh
# 构建所有示例程序
tools/build_examples.sh
# ...或仅构建一个
tools/build_examples.sh stack_example
# 试运行一个演示
./examples/bin/material_demo
./examples/bin/html_view_example
要在您自己的项目中使用 Adi2,只需添加 with "adi.gpr" 依赖——SDL 链接器选项已包含在内。库的公共规范使用了 Ada 2022 特性,因此引用 Adi.* 包的单元需要添加 pragma Ada_2022; 或使用编译选项 -gnat2022。
开始您自己的项目? docs/getting_started.md 将引导您从一个空目录开始,分别用 XML/CSS 和纯 Ada 创建一个可工作的窗口。完整的构建说明(包括不使用 Alire 的构建方法),请参阅 docs/build.md 和 docs/gprbuild_without_alire.md。
路线图
CSS。
- 扩展 CSS 覆盖面 —— 更多标准属性、选择器和值。
HTML 视图。
- 表格 ——
table、tr、td/th、列宽、合并单元格。 - Flexbox 和 Grid —— 在文档内使用
display: flex和display: grid。
控件与主题。
- 更多控件 —— 树状视图、数据网格、菜单栏、进度和忙碌指示器、工具提示、分割面板、日期和颜色选择器。
- 现成主题 —— Material、Fluent、Adwaita 和 macOS 风格,每种均提供浅色和深色版本。
文本与可达性。
- 从右到左和双向文本 ——
direction和双向文本重排。 - 无障碍访问 —— 为屏幕阅读器提供语义化角色、名称和状态,通过 AT-SPI、UI Automation 和 NSAccessibility 实现。
可移植性。
- 可插拔后端 —— 抽象层允许 Win32/Direct2D、Cocoa、GLFW、raylib 或 Skia 取代 SDL3(设计文档)。
- 嵌入式设备
创作与工具链。
- 可视化设计器 —— 类似 RAD IDE 的体验,同时编辑 UI XML 和 CSS。
- 使用 HAC 进行脚本编写 —— 嵌入 HAC Ada 编译器,以实现可重载的应用逻辑。
- XML UI 的实时重载 —— XML 控件树可像 CSS 一样热重载。
- 更完善的生成文档 —— 使用
gnatdoc生成可浏览的 API 文档。
正确性与 API。
- 改进回调 —— 允许失败的回调让应用继续运行、一次性触发的回调,以及与 UI 安全通信的后台任务(设计文档)。
- 契约 ——
Pre/Post/Type_Invariant和 SPARK 模式子集。 - C API —— 为非 Ada 调用者提供稳定的、可 C 调用的接口。
有想法?请开启一个 issue(相关策略请参阅 CONTRIBUTING.md)。
支持的平台
已在 GNU/Linux、Windows(XP, 7, 8, 10, 11,通过 MinGW)、macOS 和 WebAssembly(Emscripten)上测试。
任何其他支持 GNAT 和 SDL3 构建的环境都应该可以运行——包括 BSD 系列。渲染通过 SDL 渲染器抽象层进行,因此它会在有硬件加速的机器上使用加速,在没有的地方回退到软件渲染。正是这一点使得同一个二进制文件能在 Windows XP 和当前的桌面系统上运行。
问题解答
为什么叫 “Adi2”?为什么 Ada 包名仍然是 Adi.*?
“adi” 对搜索引擎来说太常见了——Adi2 更容易被找到。代码中的命名空间保持 Adi.* 是因为 with Adi.Widget.Button; 比 Adi2.Widget.Button 读起来更顺畅,而且重命名它会给每个源文件带来无谓的变更,却没有任何功能上的收益。项目名称 = Adi2,包名 = Adi。
相关演讲
《Ada 的原生、可移植 GUI 框架》 —— 第三届 Ada 开发者研讨会,AEiC 2026 (https://www.ada-europe.org/conference2026/workshop_adadev.html),2026年6月13日。构建一个 Adi2 应用,并通过 MCP 桥接器使用 LLM 操控运行中的 UI。
第一部分 (https://www.youtube.com/watch?v=d-RISfK9Sy8) · 第二部分 (https://www.youtube.com/watch?v=H8SMfI7dJfc)
深入了解
| 主题 | 文档 |
|---|---|
| 您的第一个 Adi2 应用 | docs/getting_started.md |
| 高层架构与核心组件 | docs/architecture.md |
| CSS 样式 — 选择器、属性、运行时 API、代码生成 | docs/css_styling.md |
| 声明式 XML UI 与控件语法 | docs/xml_ui_system.md |
| HTML 视图控件规范 | docs/html_view_spec.md |
| 静态资源打包(单二进制分发) | docs/static_assets.md |
国际化、复数形式、.po 编译 | docs/i18n.md |
| 设置存储与 JSON 后端 | docs/settings.md |
| 操作系统集成 — 对话框、剪贴板、路径 | docs/os_integration.md |
| 信号与延迟派发 | docs/signals.md |
| 抗锯齿渲染原语 | docs/rendering_aa.md |
| MCP 运行时内省与交互 | docs/mcp.md |
| 句柄所有权模型 | docs/handle_ownership.md |
| 编码规范 | docs/coding_conventions.md |
| 添加 CSS 属性 / 示例 / 测试 | docs/adding_css_property.md, docs/adding_example.md, docs/adding_test.md |
贡献
欢迎提交 issue 和拉取请求。
对于小修复以外的贡献,请先开启一个 issue 讨论方案,然后再投入时间编写代码。请遵循现有的代码风格(docs/coding_conventions.md),保持测试通过,并为新增功能添加测试。除非您明确声明,否则提交的贡献将被视为在 Apache-2.0 许可证下发布,依据其第 5 条——无需签署 CLA。详细信息请参阅 CONTRIBUTING.md。
赞助
Adi2 是独立开发和维护的。赞助资金用于支持持续维护、跨平台测试、文档编写以及公共路线图上的工作。有兴趣支持本项目或资助特定功能、移植或集成的组织:[email protected]。
赞助支持的是项目整体。如需保证响应时间或交付承诺,需要签订单独的商业协议。
许可证
Apache-2.0。详见 LICENSE。
vendor/ 目录下的第三方代码保留其原始许可证,许可证文件列在各自子目录中。大部分是宽松许可证——MIT、Apache-2.0、BSD 风格、OFL。
vendor/rlottie/src/vector/vinterpolator.cpp 是 MPL-2.0,这是一个文件级别的 Copyleft 许可证,而非宽松许可证;其文本发布在 vendor/rlottie/licenses/COPYING.MPL。
examples/assets/ 下的示例资源是演示内容,并非库的一部分;其中涉及已知第三方条款的内容已在 examples/assets/NOTICE.md 中注明。
联系方式
Adi2 由 Aldo Nicolas Bruno 编写。请通过 issue 跟踪器报告错误和建议功能。私信咨询、赞助开发或商业支持:[email protected]。
相似文章
Show HN:一个ASCII 3D渲染引擎
GlyphCSS是一个JavaScript库,它使用ASCII字符在DOM中渲染带纹理的3D网格,支持多种3D格式,并与原生JS、React和Vue集成。
Show HN:一个CSS 3D引擎(无需WebGL)
PolyCSS 是一个 CSS 多边形网格库,能将 3D 模型渲染为真实的 HTML 元素(使用 CSS matrix3d),支持 OBJ/MTL、GLB 和 VOX 格式,可与 React、Vue 或原生 JavaScript 配合使用。
CSS-DOS — 用CSS构建的计算机
一个创意项目,完全使用CSS构建类似DOS的计算机界面,展示了现代前端样式的强大功能。
Gsxui – 适用于 Go 的 Shadcn 风格组件
Gsxui 是一套面向 Go 的 Shadcn 风格组件集,支持复制集成、类型检查且使用 Tailwind 样式化的服务器端渲染 UI 组件。它提供了用于初始化和添加组件的 CLI。
Show HN: Shirei, 用原生Go编写的跨平台GUI框架
Shirei是一个为Go语言设计的跨平台GUI框架,采用即时模式API,支持在MacOS、Windows和Linux上生成原生可执行文件,无需外部依赖。