Code Monkey home page Code Monkey logo

iced_focus's Introduction

iced_focus

This crates adds a procedural macro to derive a focus chain for your application state. This allows the user of your iced application to swap the focus between the input fields of your user interface using Tab and Shift+Tab. The order of the focus chain will be derived of the order of the fields of your state. The crate iced_focus serves as a workaround until iced provides it's own focusing.

How to use

Add iced_focus to your dependencies:

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

Note: you also need iced_native for the keyboard subscription

Then derive the Focus trait for your State:

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

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

As there is no way of knowing whether a field implements a specific trait, you will have to annotate each input field with #focus(enable) to add the field to the focus chain.

To handle the keyboard input of the user add an additional message like Focus(iced_focus::Direction) to your applications message definition:

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

Add this subscription to your application ...:

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

... and handle the focus message:

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()
    }
    ...
}

Done! Happy focusing! ๐Ÿ™‚

You can specify whether the field will be added to the focus chain by providing a path to a method. The method must be of kind 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
    }
}

What is supported by this crate?

Currently, only the TextInput widget is supported as it is the only widget that supports focusing. This crate only provides a linear focus chain based on the ordering of the fields. The actual position of the element on the window in unknown to the application state.

You can derive the Focus trait for structs, tuple structs and enums:

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

You can have vecs, arrays, options or nested structs:

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.