Connector

Struct Connector 

Source
pub struct Connector<C: Component> { /* private fields */ }
Expand description

Contains the post-launch input sender and output receivers with the root widget.

The receiver can be separated from the Connector by choosing a method for handling it.

Implementations§

Source§

impl<C: Component> Connector<C>

Source

pub fn forward<X: 'static, F: Fn(C::Output) -> X + 'static>( self, sender_: &Sender<X>, transform: F, ) -> Controller<C>

Forwards output events to the designated sender.

Examples found in repository?
relm4-components/examples/adw_combo_row.rs (line 73)
62    fn init(
63        _: Self::Init,
64        root: Self::Root,
65        sender: ComponentSender<Self>,
66    ) -> ComponentParts<Self> {
67        let model = App {
68            combo_row: SimpleComboRow::builder()
69                .launch(SimpleComboRow {
70                    variants: vec!["Variant 1", "Variant 2"],
71                    active_index: None,
72                })
73                .forward(sender.input_sender(), AppMsg::Selected),
74            selected_variant: 0,
75        };
76
77        let combo_row = model.combo_row.widget();
78        let widgets = view_output!();
79
80        ComponentParts { model, widgets }
81    }
More examples
Hide additional examples
relm4/examples/message_broker.rs (line 193)
186    fn init(
187        _init: Self::Init,
188        root: Self::Root,
189        sender: ComponentSender<Self>,
190    ) -> ComponentParts<Self> {
191        let header = Header::builder()
192            .launch_with_broker((), &HEADER_BROKER)
193            .forward(sender.input_sender(), identity);
194
195        let dialog = Dialog::builder()
196            .launch(root.clone().upcast())
197            .forward(sender.input_sender(), identity);
198
199        let model = App {
200            mode: AppMode::View,
201            header,
202            dialog,
203        };
204
205        let widgets = view_output!();
206
207        ComponentParts { model, widgets }
208    }
relm4-components/examples/open_button.rs (line 58)
45    fn init(
46        _: Self::Init,
47        root: Self::Root,
48        sender: ComponentSender<Self>,
49    ) -> ComponentParts<Self> {
50        let open_button = OpenButton::builder()
51            .launch(OpenButtonSettings {
52                dialog_settings: OpenDialogSettings::default(),
53                icon: None,
54                text: "Open file",
55                recently_opened_files: Some(".recent_files"),
56                max_recent_files: 10,
57            })
58            .forward(sender.input_sender(), AppMsg::Open);
59        let model = App { open_button };
60
61        let widgets = view_output!();
62
63        ComponentParts { model, widgets }
64    }
relm4/examples/transient_dialog.rs (line 113)
101    fn init(
102        _init: Self::Init,
103        root: Self::Root,
104        sender: ComponentSender<Self>,
105    ) -> ComponentParts<Self> {
106        // We don't have access to the parent window from here
107        // but we can just use the button to set the transient window for the dialog.
108        // Relm4 will get the window later by calling [`WidgetExt::root()`]
109        // on the button once all widgets are connected.
110        let dialog = Dialog::builder()
111            .transient_for(&root)
112            .launch_with_broker((), &DIALOG_BROKER)
113            .forward(sender.input_sender(), identity);
114
115        let model = Button { dialog };
116        let widgets = view_output!();
117        ComponentParts { model, widgets }
118    }
119
120    fn update(&mut self, _msg: Self::Input, _sender: ComponentSender<Self>) {}
121}
122
123#[derive(Debug)]
124enum AppMsg {}
125
126struct App {
127    button: Controller<Button>,
128}
129
130#[relm4::component]
131impl SimpleComponent for App {
132    type Init = ();
133    type Input = AppMsg;
134    type Output = ();
135
136    view! {
137        main_window = gtk::ApplicationWindow {
138            set_default_size: (500, 250),
139            set_child: Some(model.button.widget()),
140        }
141    }
142
143    fn init(
144        _init: Self::Init,
145        root: Self::Root,
146        sender: ComponentSender<Self>,
147    ) -> ComponentParts<Self> {
148        let button = Button::builder()
149            .launch(())
150            .forward(sender.input_sender(), identity);
151        let model = App { button };
152        let widgets = view_output!();
153        ComponentParts { model, widgets }
154    }
relm4-components/examples/combo_box.rs (line 88)
72    fn init(
73        _: Self::Init,
74        root: Self::Root,
75        sender: ComponentSender<Self>,
76    ) -> ComponentParts<Self> {
77        let default_idx = 0;
78
79        let langs = vec![
80            "English", "German", "French", "Polish", "Russian", "Chinese",
81        ];
82
83        let combo = SimpleComboBox::builder()
84            .launch(SimpleComboBox {
85                variants: langs,
86                active_index: Some(default_idx),
87            })
88            .forward(sender.input_sender(), AppMsg::ComboChanged);
89
90        let model = App {
91            combo,
92            idx: default_idx,
93        };
94
95        let combo = model.combo.widget();
96        let widgets = view_output!();
97
98        ComponentParts { model, widgets }
99    }
relm4/examples/components.rs (line 184)
177    fn init(
178        _: Self::Init,
179        root: Self::Root,
180        sender: ComponentSender<Self>,
181    ) -> ComponentParts<Self> {
182        let header = Header::builder()
183            .launch(())
184            .forward(sender.input_sender(), identity);
185        let dialog = Dialog::builder()
186            .transient_for(&root)
187            .launch(DialogInit {
188                text: "Do you want to close before saving?".to_string(),
189                secondary_text: Some("All unsaved changes will be lost".to_string()),
190                accept_text: "Close".to_string(),
191                cancel_text: "Cancel".to_string(),
192            })
193            .forward(sender.input_sender(), identity);
194
195        let model = App {
196            mode: AppMode::View,
197            header,
198            dialog,
199        };
200        let widgets = view_output!();
201
202        ComponentParts { model, widgets }
203    }
Source

pub fn connect_receiver<F: FnMut(&mut Sender<C::Input>, C::Output) + 'static>( self, func: F, ) -> Controller<C>

Given a mutable closure, captures the receiver for handling.

Examples found in repository?
relm4/examples/settings_list.rs (lines 29-68)
18fn main() {
19    gtk::Application::builder()
20        .application_id("org.relm4.SettingsListExample")
21        .launch(|_app, window| {
22            // Initialize a component's root widget
23            let mut component = AppModel::builder()
24                // Attach the root widget to the given window.
25                .attach_to(&window)
26                // Start the component service with an initial parameter
27                .launch("Settings List Demo".into())
28                // Attach the returned receiver's messages to this closure.
29                .connect_receiver(move |sender, message| match message {
30                    Output::Clicked(id) => {
31                        eprintln!("ID {id} Clicked");
32
33                        match id {
34                            0 => xdg_open("https://github.com/Relm4/Relm4".into()),
35                            1 => xdg_open("https://docs.rs/relm4/".into()),
36                            2 => {
37                                sender.send(Input::Clear).unwrap();
38                            }
39                            _ => (),
40                        }
41                    }
42
43                    Output::Reload => {
44                        sender
45                            .send(Input::AddSetting {
46                                description: "Browse GitHub Repository".into(),
47                                button: "GitHub".into(),
48                                id: 0,
49                            })
50                            .unwrap();
51
52                        sender
53                            .send(Input::AddSetting {
54                                description: "Browse Documentation".into(),
55                                button: "Docs".into(),
56                                id: 1,
57                            })
58                            .unwrap();
59
60                        sender
61                            .send(Input::AddSetting {
62                                description: "Clear List".into(),
63                                button: "Clear".into(),
64                                id: 2,
65                            })
66                            .unwrap();
67                    }
68                });
69
70            // Keep runtime alive after the component is dropped
71            component.detach_runtime();
72
73            println!("parent is {:?}", component.widget().toplevel_window());
74        });
75}
Source

pub fn detach(self) -> Controller<C>

Ignore outputs from the component and finish the builder.

Examples found in repository?
relm4-components/examples/web_image.rs (line 71)
66    fn init(
67        _: Self::Init,
68        root: Self::Root,
69        sender: ComponentSender<Self>,
70    ) -> ComponentParts<Self> {
71        let image = WebImage::builder().launch(IMAGES[0].to_owned()).detach();
72        let model = App { image, idx: 0 };
73
74        let image = model.image.widget();
75        let widgets = view_output!();
76
77        ComponentParts { model, widgets }
78    }
Source

pub fn into_stream(self) -> ComponentStream<C>

Convert his type into a Stream that yields output events as futures.

Examples found in repository?
relm4/examples/message_stream.rs (line 149)
141    fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>, root: &Self::Root) {
142        match msg {
143            AppMsg::StartSearch => {
144                self.searching = true;
145
146                let stream = Dialog::builder()
147                    .transient_for(root)
148                    .launch(())
149                    .into_stream();
150                sender.oneshot_command(async move {
151                    // Use the component as stream
152                    let result = stream.recv_one().await;
153
154                    if let Some(search) = result {
155                        let response =
156                            reqwest::get(format!("https://duckduckgo.com/lite/?q={search}"))
157                                .await
158                                .unwrap();
159                        let response_text = response.text().await.unwrap();
160
161                        // Extract the url of the first search result.
162                        if let Some(url) = response_text.split("<a rel=\"nofollow\" href=\"").nth(1)
163                        {
164                            let url = url.split('\"').next().unwrap().replace("amp;", "");
165                            Some(format!("https:{url}"))
166                        } else {
167                            None
168                        }
169                    } else {
170                        None
171                    }
172                });
173            }
174        }
175    }

Trait Implementations§

Source§

impl<C: Component> ComponentController<C> for Connector<C>

Source§

fn sender(&self) -> &Sender<C::Input>

Provides access to the component’s sender.
Source§

fn state(&self) -> &StateWatcher<C>

Provides access to the state of a component.
Source§

fn widget(&self) -> &C::Root

Returns the root widget of the component.
Source§

fn detach_runtime(&mut self)

Dropping this type will usually stop the runtime of the component. With this method you can give the runtime a static lifetime. In other words, dropping the controller or connector will not stop the runtime anymore, instead it will run until the app is closed.
Source§

fn emit(&self, event: C::Input)

Emits an input to the component.
Source§

fn model(&self) -> Ref<'_, C>

Returns a reference to the Component.
Source§

fn widgets(&self) -> Ref<'_, C::Widgets>

Returns a reference to the Component::Widgets.
Source§

impl<C> Debug for Connector<C>
where C: Component + Debug, C::Widgets: Debug,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<C> Freeze for Connector<C>
where <C as Component>::Root: Freeze,

§

impl<C> !RefUnwindSafe for Connector<C>

§

impl<C> !Send for Connector<C>

§

impl<C> !Sync for Connector<C>

§

impl<C> Unpin for Connector<C>
where <C as Component>::Root: Unpin,

§

impl<C> !UnwindSafe for Connector<C>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<C> AsyncPosition<()> for C

Source§

fn position(_index: usize)

Returns the position. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<C, I> Position<(), I> for C

Source§

fn position(&self, _index: &I)

Returns the position. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more