#focus #interface #ui #graphics

iced_focus

为 Iced 应用程序推导焦点链的 proc-macro

2 个版本

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

#757 in GUI

MIT 许可证

14KB
200

iced_focus

此包添加了一个过程宏,用于为您的应用程序状态推导焦点链。这允许您的 iced 应用程序用户通过使用 TabShift+Tab 在用户界面的输入字段之间切换焦点。焦点链的顺序将推导自状态的字段顺序。此包 iced_focus 作为一个解决方案,直到 iced 提供自己的焦点。

如何使用

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
    }
}

此包支持什么?

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

您可以推导结构体、元组结构体和枚举的 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,
    )
}

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

#[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,
}

依赖项

~2–17MB
~234K SLoC