#focus #interface #ui #graphics #gui

iced_focus_derive

一个用于为Iced应用程序生成焦点链的进程宏

2个版本

0.1.1 2021年8月13日
0.1.0 2021年8月11日

67#focus


用于 iced_focus

MIT 协议

19KB
436

iced_focus

此crate添加了一个进程宏,用于为您的应用程序状态生成焦点链。这允许您的iced应用程序的用户通过使用TabShift+Tab在用户界面的输入字段之间切换焦点。焦点链的顺序将根据您状态的字段顺序推导出来。直到iced提供自己的焦点功能之前,iced_focus crate充当一个解决方案。

如何使用

iced_focus 添加到您的依赖项中

[dependencies]
iced_focus = { version = "0.1.1", features = ["derive"] }
iced = "0.3.0"
iced_native = "0.4.0"

注意:您还需要 iced_native 以进行键盘订阅

然后为您的 State 导出 Focus 特性

use iced::text_input;
use iced_focus::Focus;

#[derive(Focus)]
struct Example {
    text: String,
    #[focus(enable)]
    text_input: text_input::State,
}

由于无法知道字段是否实现了特定的特性,您必须使用 #focus(enable) 注释每个输入字段,以将字段添加到焦点链。

要处理用户的键盘输入,请向您的应用程序的消息定义中添加一个额外的消息,如 Focus(iced_focus::Direction)

enum Message {
    TextInput(String),
    // Add this:
    Focus(iced_focus::Direction),
}

将此订阅添加到您的应用程序 ...

impl Application for Example {
    ...
    fn subscription(&self) -> Subscription<Message> {
        iced_native::subscription::events_with(|event, _status| {
            if let iced_native::Event::Keyboard(iced::keyboard::Event::KeyPressed {
                key_code: iced_native::keyboard::KeyCode::Tab,
                modifiers,
            }) = event
            {
                Some(Message::Focus(if modifiers.shift {
                    iced_focus::Direction::Backwards
                } else {
                    iced_focus::Direction::Forwards
                }))
            } else {
                None
            }
        })
    }
    ...
}

... 并处理焦点消息

impl Application for Example {
    ...
    fn update(...) -> iced::Command<Self::Message> {
        match message {
            Message::TextInput(value) => self.text = value,

            // Add this:
            Message::Focus(direction) => {
                let _ = self.focus(direction);
            }
        }

        iced::Command::none()
    }
    ...
}

完成!祝您聚焦愉快! 🙂

您可以通过提供方法路径来指定字段是否将被添加到焦点链中。该方法必须是类型 Fn(&self) -> bool 的函数。

struct Example {
    text: String,
    enable: bool,
    #[focus(enable = "self.enable_text_input")]
    text_input: text_input::State,
}

impl Example {
    fn enable_text_input(&self) -> bool {
        self.enable
    }
}

此crate支持什么?

目前,仅支持 TextInput 小部件,因为它是目前唯一支持焦点的组件。此crate仅提供基于字段排序的线性焦点链。元素在窗口中的实际位置对应用程序状态来说是未知的。

您可以推导结构体、元组结构和枚举的 Focus 特性

#[derive(Focus)]
struct ExampleTuple (
    String,
    #[focus(enable)]
    text_input::State,
);

#[derive(Focus)]
enum ExampleEnum {
    Unit,
    Named {
        text: String,
        #[focus(enable)]
        text_input: text_input::State,
    },
    Unnamed (
        String,
        #[focus(enable)]
        text_input::State,
    )
}

您可以拥有vecs、数组、选项或嵌套结构体

#[derive(Focus)]
struct ExampleVec {
    #[focus(enable)]
    text_inputs: Vec<text_input::State>,
}

#[derive(Focus)]
struct ExampleArray {
    #[focus(enable)]
    text_inputs: [text_input::State; 10],
}

#[derive(Focus)]
struct ExampleOption {
    #[focus(enable)]
    text_input: Option<text_input::State>,
}

#[derive(Focus)]
struct Example {
    #[focus(enable)]
    vec: ExampleVec,

    #[focus(enable)]
    array: ExampleArray,

    #[focus(enable)]
    option: ExampleOption,
}

依赖项

~1.5MB
~35K SLoC