#view #reactive #macro

声明式

用于简化视图代码操作的泛型 DSL 宏

12 个版本 (6 个重大变更)

0.7.0 2024年4月27日
0.6.0 2023年10月4日
0.5.3 2023年6月15日
0.4.1 2023年5月31日
0.1.0 2023年5月6日

#161 in GUI

Download history 136/week @ 2024-04-22 33/week @ 2024-04-29 25/week @ 2024-07-01 75/week @ 2024-07-29

每月75次下载

Apache-2.0 OR MIT

25KB
151

declarative

REUSE status On crates.io

一个进程宏库,实现了一个通用的 DSL,以简化创建复杂响应式视图代码,使其更易于编辑和维护。

要使用它,请在您的 Cargo.toml 中添加以下内容

[dependencies.declarative]
version = '0.7.0'

要了解如何使用宏,目前最好的方式是克隆仓库,按字母顺序阅读示例的源代码,并像这样运行它们

cargo run --example EXAMPLE_NAME

示例依赖于 gtk-rs,因此在开始之前您应该熟悉 gtk-rs
https://gtk-rs.org/gtk4-rs/stable/latest/book/

除了宏功能外,示例还展示了某些使用模式(模板、组件、Elm 等)。由于 GTK 的面向对象特性,它有自己的模式,而 declarative 与其很好地集成,但还没有示例(这将非常冗长,并且仅限于 GTK,而 declarative 并非基于 GTK)。

计数器应用程序示例

以下是用 gtk-rs 实现的 Elm 架构的示例

Light theme app screenshot Dark theme app screenshot

use declarative::{block as view, clone, construct};
use gtk::{glib, prelude::*};

enum Msg { Increase, Decrease }

// syntactic sugar for sending messages:
macro_rules! send { [$msg:expr => $tx:expr] => [$tx.send_blocking($msg).unwrap()] }

fn start(app: &gtk::Application) {
    let (tx, rx) = async_channel::bounded(1);
    let mut count = 0; // the state

    view![ gtk::ApplicationWindow window {
        application: app
        title: "My Application"
        titlebar: &gtk::HeaderBar::new()

        child: &_ @ gtk::Box {
            orientation: gtk::Orientation::Vertical
            spacing: 6
            margin_top: 6
            margin_bottom: 6
            margin_start: 6
            margin_end: 6
            ~
            append: &_ @ gtk::Label {
                label: "Count unchanged"
                'bind set_label: &format!("The count is: {count}")
            }
            append: &_ @ gtk::Button {
                label: "Increase" ~
                connect_clicked: clone![tx; move |_| send!(Msg::Increase => tx)]
            }
            append: &_ @ gtk::Button::with_label("Decrease") {
                connect_clicked: move |_| send!(Msg::Decrease => tx)
            }
            'consume refresh = move |count| bindings!()
        }
    } ];

    let update = |count: &mut u8, msg| match msg {
        Msg::Increase => *count = count.wrapping_add(1),
        Msg::Decrease => *count = count.wrapping_sub(1),
    };

    glib::spawn_future_local(async move {
        while let Ok(msg) = rx.recv().await {
            update(&mut count, msg); // the state is updated
            refresh(count); // now the view is refreshed
        }
    });

    window.present()
}

fn main() -> glib::ExitCode {
    let app = gtk::Application::default();
    app.connect_activate(start);
    app.run()
}

要执行,请运行

cargo run --example y_readme

基本维护

以下命令必须执行,并且不应出现任何问题

cargo check  -p declarative-macros
cargo clippy -p declarative-macros
cargo test   -p declarative-macros
cargo check
cargo clippy
cargo test
# and now run and check each example

如果您需要变更日志,可能提交日志会有帮助(最后几个尝试包含最重要的细节)。


许可协议

许可协议为 Apache License,版本 2.0 (Apache-2.0.txthttps://apache.ac.cn/licenses/LICENSE-2.0) 或 MIT 许可证 (MIT.txthttp://opensource.org/licenses/MIT),您可任选其一。

除非您明确声明,否则根据 Apache-2.0 许可证定义的,您有意提交以包含在本作品中的任何贡献,都应按上述方式双重许可,不附加任何额外的条款或条件。

依赖项

~0.7–1.2MB
~25K SLoC