1 个不稳定版本
0.3.0 | 2024年4月11日 |
---|
#167 在 国际化 (i18n)
245KB
5.5K SLoC
{iced} 应用框架
Rizzen Yazston :iced-url: https://crates.io/crates/iced :iced_aw-url: https://crates.io/crates/iced_aw :i18n-url: https://crates.io/crates/i18n-rizzen-yazston :icu-url: https://crates.io/crates/icu :icu4x-url: https://icu4x.unicode.org/ :iced: pass:q[iced]
欢迎使用 {iced} 应用框架 项目。
目标是提供一个用于开发原生多窗口 {iced} 应用程序的起始框架。
该项目使用 {iced-url}[{iced}] 库 Crates(包括 {iced_aw-url}[iced_aw] 社区 Crates 以提供额外的控件)来构建应用程序的 GUI。
此外,框架通过使用 {i18n-url}[i18n-rizzen-yazston] Crates 和 {icu4x-url}[ICU4X] 项目的各种 Crates(主 Crates 为 {icu-url}[icu])作为功能选项来支持国际化。
为了支持各种应用程序,所有应用程序的功能能力都通过构建功能选项进行了限制(请参阅功能部分)。未使用的功能可以简单地从应用程序中删除,从而通过减少对 #[cfg(...)]
和 #[cfg(not()...)]
语句的需求来简化源代码。
功能
以下功能可用
-
log
:启用应用程序的日志记录,并在首选项窗口中插入日志级别设置, -
sync
:使用sync::Arc
而不是rc::Rc
,以及它们各自的变体。 -
i18n
:启用国际化支持。设计允许所有脚本,尽管目前仅支持自上而下的脚本,因为icu
目前仅具有自上而下的脚本流向信息(计划扩展到所有脚本)。使用最新的i18n
版本 0.9.1,该版本添加了新功能。 -
persistent
:指定是否在退出时保存会话数据,并在应用程序启动时恢复。如果想要应用程序设置在使用过程中持久存在,则此功能是必需的。 -
first_use
:启用简化首用偏好设置窗口,在首次使用时首先显示,允许用户设置特定的偏好设置,然后再打开应用程序的主窗口。此功能会自动启用persistent
功能。 -
clap
:启用命令行支持,适用于喜欢将选项/命令等传递给应用程序的应用程序。注意使用的版本是 4.4.3,因为 4.5 需要 rustc 版本 0.74。
在 Cargo.toml
中有两行 default
,其中一行已被注释。一行启用所有功能,而另一行则启用无功能。
包含的内容
应用程序框架具有以下功能
-
如果为应用程序构建了
first_use
和i18n
功能,则偏好设置窗口将在首次使用时显示,提示用户选择用户界面语言(目前正在使用语言标签,等待 ICU4X 中的 display name 功能完成), -
以下窗口
-
ConfirmExit
:用于演示目的,应用程序在退出时被设置为显示(模拟未保存的数据), -
Preferences
:包含用户界面语言设置和可选的日志级别设置, -
FatalError
:用于向用户显示致命错误消息(当未从控制台启动时很有用), -
Information
:一个简单的通用窗口,用于向用户显示消息, -
Main
:仅包含菜单栏, -
About
:简单地演示关于窗口。 -
当弹出窗口显示时,通常禁用父窗口,
-
捕获窗口装饰关闭按钮,以处理某些状态情况,
-
窗口可调整大小和位置,并且如果构建了
persistent
功能,则其最终位置和大小将在应用程序终止时保存,并在应用程序重新启动时恢复。 -
支持内部处理
Result
错误的update()
方法以及 'Application::new()' 方法,使用致命错误窗口显示未捕获的错误。 -
支持国际化的文本和错误本地化。包含两个用于几乎所有文本的演示语言。故意不将主窗口中显示的文本本地化,以进行演示。
-
对于选定平台上的本地化提供了一个简单的示例。对于 MacOS 目标,菜单栏和确认退出窗口使用 "退出 <app_name>" 而不是 "退出"。
使用方法
注意:没有包含构建脚本,并且需要将数据文件复制到目标位置。
由于此项目是多窗口 {iced} 应用程序开发的起点,它可以编译成一个功能示例,并通过使用应用程序名称 example
来启动。
在启动 example
之前,将 l10n
目录复制到二进制文件所在的目录,以避免因缺少本地化数据库而导致的恐慌。
编辑项目根目录下的 lib.rs
,以配置各种应用程序的 const
以反映新的项目。
由于这是一个用于创建多窗口应用的微型应用框架,您可以自由删除不需要的功能,这些功能可以通过 #[cfg(...)]
语句和删除相关的语句/表达式来轻松识别。或者,您可以保留这些功能不变,并继续使用新窗口和现有窗口的新组件的 #[cfg(...)]
语句,以便在以后方便切换到更高级的功能(如国际支持或突然需要命令行选项)。
注意
-
菜单项始终居中,
iced_aw
中menu
的当前实现没有方法或手段来更改对齐以从开始或结束。 -
这仍然是一个正在进行中的项目,因此窗口可能看起来有点奇怪。目前更注重功能而不是外观。
添加新的窗口
-
在
src/window
目录中,选择一个与您的新窗口布局结构最接近的窗口,复制一个带有新文件名的 Rust 文件。 -
在新窗口的
.rs
文件中进行必要的更改 -
例如,重命名
???Localisation
结构体,???
结构体和display_???
函数,其中 ??? 是窗口缩写名称。根据需要调整这些内容。 -
如有必要,添加一个
???Message
枚举和一个update_???
函数,其中 ??? 是内部窗口缩写名称。请参阅现有的preferences.rs
以获取示例。 -
修改
try_new()
、try_update()
和view()
的内容,并可选地调整parent_remove()
。 -
在
window.rs
中添加新文件名。 -
在
core/session.rs
中为窗口在Ui
结构体中添加条目。 -
在
core/application
-
将
use crate::{ ... window::{
语句中添加新窗口文件名。 -
向
WindowType
添加新窗口的条目。 -
如果新窗口有自己的
Message
枚举,将其添加到ApplicationMessage
枚举中,以便能够将消息传递到新窗口的try_update()
方法。 -
针对
try_update()
方法,为新的窗口添加匹配分支,可以是直接添加到窗口的try_update()
方法中,或者如果需要在窗口的try_update()
方法之外执行更多逻辑,可以在新窗口的Rust文件中添加一个update_?
函数,其中?是窗口的缩写。参见其他分支的示例。 -
为
resized()
和moved()
方法添加新的窗口条目。 -
如果新的窗口可以通过应用程序的菜单栏访问,则请在
window/main/menu_bar.rs
中添加条目,并将匹配分支添加到update_main()
函数中,以处理新窗口的显示。
设计流程
几乎所有的i18n
库方法都使用Result
类型来能够提供可捕获的运行时错误,应用程序的开发者(或另一个库)可以决定忽略错误、显示错误或未捕获的错误成为致命错误(应用程序终止)。这是i18n
项目的有意设计。
另一方面,iced
库不支持将Result
类型作为new()
、update()
和view()
方法的返回类型。需要捕获和处理i18n
各种方法的Result
。
创建了一种新的更新方法,称为 try_update()
,该方法包含原本在应用程序的 update()
方法中所有的逻辑,并返回一个 Result
类型。该方法在 update()
中被调用,如果结果是 Ok()
变体,则将 Command
枚举返回给 iced
调用者。然而,如果结果是 Err()
变体,则创建包含错误的 FatalError
状态,并将生成的窗口创建命令返回给 iced
调用者。显示的致命错误窗口是一种特殊类型的窗口,它不允许返回 Err()
变体。在致命错误窗口的 try_update()
方法中发生的任何错误都被捕获和处理,因此只返回包含关闭所有窗口的批量命令的 Ok()
变体。在应用程序关闭之前显示运行时致命错误的好处是,当应用程序不是从通常显示错误的控制台启动,并且不支持将错误记录到日志系统(通常是文件)时。
对于 new()
方法也使用了类似的方法,实际的逻辑放在一个新的方法 try_new()
中。如果结果是错误,则应用程序以包含错误简单格式化消息的 panic!()
终止。否则,返回 Ok()
变体的内容。
没有与view()
方法等价的try_view()
方法,因为不应当发生错误。view()
方法必须只读取窗口状态,并根据该状态构建窗口。在创建时的窗口状态必须包含所有需要显示的数据,无需任何格式化。view()
方法仅允许通过读取窗口状态的字段来更改放置顺序。如果启用了功能i18n
,则文本本地化仅在窗口状态的创建时,或在更新窗口状态的try_update()
和try_update_localisation()
方法中进行。然而,应用程序的主view()
方法在检索窗口的实际view()
时,会捕获两种可能的错误,在这种情况下,主窗口的内容会被错误信息替换。
如上所示,有关于应用程序主try_update()
和view()
方法的引用,调用窗口的实际try_update()
和view()
。将更新和视图逻辑分离到每个窗口自己的方法中,这种方法是因为匹配语句变得过于庞大,难以理解各个窗口的逻辑。为此,引入了WindowType
和WindowTrait
(以及WindowTrait
以实现从Any
向下转换),以提供一个调用窗口实际try_update()
和view()
方法的统一方式。这还允许使用枚举WindowType
将窗口编号或标识符作为String
使用,当存在多个相同类型的窗口时。在窗口的try_update()
和view()
方法中,枚举变体的值用于对特定窗口的WindowType
变体进行更改。
如果应用程序的主要 Message
枚举中没有包含适当的消息处理,则 Message
枚举将被分解为单独的 Message
枚举,每个窗口一个。
依赖关系
~31–58MB
~874K SLoC