libcosmic/crates/component-system
2022-01-31 15:55:55 +01:00
..
examples/basic chore: Sync with Relm4 new-approach branch 2022-01-31 15:55:55 +01:00
src chore: Sync with Relm4 new-approach branch 2022-01-31 15:55:55 +01:00
Cargo.toml chore: Sync with Relm4 new-approach branch 2022-01-31 15:55:55 +01:00
README.md chore: Sync with Relm4 new-approach branch 2022-01-31 15:55:55 +01:00

COSMIC Component System

This library is a prototyping area for a rewrite of Relm4's component system.

Using a Macro to Define a Component

The simplest way to define a component is to use the component!() macro.

pub enum MyCustomInputMessage {
    Variant1,
    Variant2,
}

pub enum MyCustomCommand {
    Action
}

component! {
    // The model stores the state of this component.
    pub struct MyCustomModel {
        pub state: String,
    }

    // Widgets managed by the view are stored here.
    pub struct MyCustomWidgets {
        description: gtk::Label,
    }

    // The type of the input sender
    type Input = MyCustomInputMessage;

    // The type of the output sender
    type Output = ();

    // Declares the root widget and how it should be constructed.
    type Root = gtk::Box {
        ccs::view! {
            root = gtk::Box {
                set_orientation: gtk::Orientation::Vertical,
            }
        }

        root
    };

    // Constructs the inner component's model and widgets, using the
    // initial parameter given by `args`.
    fn init(args: (), root, input, output) {
        let description = gtk::Label::new();

        root.append(&description);

        Fuselage {
            model: MyCustomModel { state: String::new() },
            widgets: MyCustomWidgets { description },
        }
    }

    // Updates the model and view. `self` is the model.
    fn update(&mut self, widgets, event, input, output) {
        match event {
            MyCustomInputMessage::Variant1 => {

            }

            MyCustomInputMessage::Variant2 => {

            }
        }

        Some(MyCustomCommand::Action)
    }

    async fn command(command: MyCustomCommand, input) {

    }
}

Components can be created and have their output events forwarded:

let counter = InfoButton::init()
    .launch("Clicked 0 times".into(), "Click".into())
    .forward(input.clone(), |event| match event {
        InfoButtonOutput::Clicked => AppEvent::Increment
    });

The handle returned can be used to emit inputs to it, and to get the root widget.

counter.emit(InfoButtonInput::SetDescription(format!("Clicked {} times", count)));

box.append(&counter.widget);