### Install Adwaita Demo Application Source: https://github.com/relm4/book/blob/main/src/tricks.md Provides the command-line instructions to install the Adwaita demo application using Flatpak. This requires adding the gnome-nightly Flatpak remote first. The demo application showcases Adwaita widgets and styling. ```bash flatpak remote-add --if-not-exists gnome-nightly https://nightly.gnome.org/gnome-nightly.flatpakrepo flatpak install gnome-nightly org.gnome.Adwaita1.Demo ``` -------------------------------- ### Install ASHPD Demo Application Source: https://github.com/relm4/book/blob/main/src/tricks.md Provides the command-line instructions to install the ASHPD (A Simple Host Port Definition) demo application using Flatpak. This demo application is useful for exploring portal functionalities. ```bash flatpak install flathub com.belmoussaoui.ashpd.demo ``` -------------------------------- ### Complete Async Component Example in Rust Source: https://github.com/relm4/book/blob/main/src/threads_and_async/async.md Presents a full example of an asynchronous component in Rust, integrating initialization, loading widgets, and the update function. This serves as a comprehensive reference for implementing async components. ```rust #[relm4::component(async)] impl AsyncComponent for App { type Init = (); type Input = AppMsg; type Output = (); type CommandOutput = (); view! { // ... view definition ... } async fn init( _init: Self::Init, root: Self::Root, sender: ComponentSender, ) -> AsyncComponentParts { // ... initialization logic ... let model = App {}; let parts = ComponentParts { model, view: view! { // ... view widgets ... }, }; AsyncComponentParts { // ... parts ... } } async fn init_loading_widgets(&self, _root: &Self::Root) -> HtmlEscaped { // ... loading widgets definition ... html_escaped! { // ... spinner or other loading indicators ... } } async fn update(&mut self, message: Self::Input, sender: ComponentSender) { match message { // ... message handling ... } } } ``` -------------------------------- ### Install GTK4 Demo Application Source: https://github.com/relm4/book/blob/main/src/tricks.md Provides the command-line instructions to install the GTK4 demo application using Flatpak. This requires adding the gnome-nightly Flatpak remote first. The demo application is useful for exploring GTK4 widgets and features. ```bash flatpak remote-add --if-not-exists gnome-nightly https://nightly.gnome.org/gnome-nightly.flatpakrepo flatpak install gnome-nightly org.gtk.Demo4 ``` -------------------------------- ### Complete Minimal Working Example for CLI Argument Handling Source: https://github.com/relm4/book/blob/main/src/cli.md A complete Rust program demonstrating the integration of clap for CLI argument parsing with Relm4/GTK applications. It includes the argument struct definition, the main function for parsing and launching the application, and basic debug output to show how arguments are handled. This example serves as a runnable template for CLI argument management. ```rust use clap::Parser; use relm4::prelude::*; #[derive(Parser)] #[clap(author, version, about, long_about = None)] struct Args { #[clap(skip)] gtk_options: Vec, #[clap(long)] non_gtk_arg: bool, } struct App; #[relm4::component] impl SimpleComponent for App { type Init = (); type Input = (); type Output = (); view! { gtk::Window { set_title[self] "CLI Example"; set_default_size[self] (400, 300); } } fn init( _init: Self::Init, root: Self::Root, _sender: ComponentSender, ) -> ComponentParts { let model = App; let widgets = view_output!(); ComponentParts { model, widgets } } } fn main() -> Result<(), Box> { let args = Args::parse(); println!("Non-GTK arg: {}", args.non_gtk_arg); println!("GTK options: {:?}", args.gtk_options); let mut gtk_args = vec![std::env::args().next().unwrap()]; gtk_args.extend(args.gtk_options); let app = RelmApp::with_args(gtk_args).launch(App::new())?; Ok(()) } ``` -------------------------------- ### Complete Relm4 Application Code Example in Rust Source: https://github.com/relm4/book/blob/main/src/efficient_ui/factory.md Presents the entire code for a Relm4 application, combining initialization, widget view, update logic, and the main function into a single, runnable example. ```rust use relm4::prelude::*; #[derive(Debug)] enum AppMsg { Increment, Counter(CounterMsg), } struct Application { counter_box: FactoryVecDeque, widgets: ApplicationWidgets, } #[derive(Debug)] struct Counter { value: i32 } impl Counter { fn new(value: i32) -> Self { Self { value } } } #[derive(Debug)] enum CounterMsg { Increment, } impl Component for Counter { type Init = i32; type Input = CounterMsg; type Output = (); type Root = gtk::Box; type Command = (); fn init(init: Self::Init, _sender: ComponentSender) -> Controller { let model = Counter::new(init); let widgets = view_widgets!(model); Self::controller(model, widgets) } view! { gtk::Box { set_spacing: 5, set_homogeneous: true, #[name = "label"] gtk::Label { set_margin_all: 5, set_label: "Counter: ", }, gtk::Label { set_label: &self.value.to_string(), } } } fn update(&mut self, msg: Self::Input, _sender: ComponentSender) { match msg { CounterMsg::Increment => { self.value += 1; } } } } impl Application { fn init( &mut self, _sender: ComponentSender, ) -> Controller { let counter_box = FactoryVecDeque::builder() .launch(Counter::new(0)) .forward(_sender.clone(), |msg| AppMsg::Counter(msg)); let widgets = view_widgets!(counter_box.clone()); Self::controller(Self { counter_box, widgets }) } } impl Component for Application { type Input = AppMsg; type Output = (); type Init = (); type Root = gtk::Box; type Command = (); fn init(_init: Self::Init, _sender: ComponentSender) -> Controller { let counter_box = FactoryVecDeque::builder() .launch(Counter::new(0)) .forward(_sender.clone(), |msg| AppMsg::Counter(msg)); let widgets = view_widgets!(counter_box.clone()); Self::controller(Self { counter_box, widgets }) } view! { gtk::Box { set_vertical: true, #[local_ref] counter_box -> gtk::Box { set_homogeneous: true, set_spacing: 5, }, button = gtk::Button { set_label: "Increment", connect_clicked[sender] => move |_| { sender.send(AppMsg::Increment).unwrap(); } } } } fn update(&mut self, msg: AppMsg, _sender: ComponentSender) { match msg { AppMsg::Increment => { let mut guard = self.counter_box.guard(); guard.iter_mut().for_each(|counter| counter.value += 1); } AppMsg::Counter(msg) => { self.counter_box.update_each(msg); } } } } fn main() { Application::run::(Default::default()).expect("Failed to run application"); } ``` -------------------------------- ### Rust: Handling Slow Update with Key Generation Source: https://github.com/relm4/book/blob/main/src/threads_and_async/index.md Illustrates how a slow CPU-bound operation (RSA key generation) within an update function can freeze the application. This example shows the direct call to `generate_rsa_key` which would block the UI. It receives a `GenerateKey` message and attempts to process it. ```rust enum Msg { GenerateKey, KeyGenerated(String), } // ... inside impl Component ... fn update(&mut self, msg: Msg, _sender: Sender) { match msg { Msg::GenerateKey => { // This call will block the UI thread let key = generate_rsa_key(); self.sender.send(Msg::KeyGenerated(key)).unwrap(); } Msg::KeyGenerated(key) => { // Update UI with the key println!("Key generated: {}", key); } } } ``` -------------------------------- ### Rust: Asynchronous RSA Key Fetching Function Source: https://github.com/relm4/book/blob/main/src/threads_and_async/index.md Shows an example of an I/O-bound operation using async/await to fetch RSA keys from a server. This function is non-blocking, allowing the application to remain responsive while waiting for the network response. It returns a `Result` containing the fetched key or an error. ```rust async fn fetch_rsa_key() -> Result { let response = reqwest::get("http://example.com/keys/rsa").await?; let key = response.text().await?; Ok(key) } ``` -------------------------------- ### Complete Simple Manual Application Code (Rust) Source: https://github.com/relm4/book/blob/main/src/first_app.md This Rust code snippet represents the entire source code for the simple manual example. It showcases the integration of Relm4 components, including widgets, event handling, and application logic. No external dependencies beyond the Relm4 framework are explicitly shown here, but standard Rust libraries are implicitly used. ```rust use gtk::prelude::*; use relm4::prelude::*; struct App { counter: i32, } #[derive(Debug)] enum AppMsg { Increment, Decrement, } impl SimpleComponent for App { type Init = (); type Input = AppMsg; type Output = (); type Root = gtk::Box; fn init( _init: Self::Init, root: Self::Root, _sender: ComponentSender, ) -> ComponentParts { let model = App { counter: 0 }; let label = gtk::Label::new(Some("0")); root.append(&label); ComponentParts { model, view: (label,), } } fn update(&mut self, msg: AppMsg, sender: ComponentSender) { match msg { AppMsg::Increment => { self.counter += 1; } AppMsg::Decrement => { self.counter -= 1; } } sender.emit(AppMsg::Increment); } fn view(&self, label: >k::Label) { label.set_text(&self.counter.to_string()); } } fn main() { let app = RelmApp::::new(); app.run(()); } ``` -------------------------------- ### Generated Pre-Initialization Code in Rust Source: https://github.com/relm4/book/blob/main/src/component_macro/expansion.md Displays the Rust code generated by the `component` macro that executes before the main widget initialization. This section often contains setup logic derived from the `view_output!()` entrypoint. ```rust // Code generated before widget initialization // ... ``` -------------------------------- ### Complete Relm4 Application Code with #[track] Source: https://github.com/relm4/book/blob/main/src/efficient_ui/tracker.md This comprehensive Rust code example presents a complete Relm4 application, integrating the `#[track]` attribute for conditional widget updates, custom CSS styling, and model initialization. It serves as a reference for how all components work together. ```rust #[relm4::relm_model] struct AppModel { counter: i32, #[tracker] tracker: i32, } #[derive(Debug)] enum AppMsg { Increment, } struct App; #[relm4::view] impl AppModel { fn init(#[start] model: Self) -> Self { let view = Self::view(model.counter, model.tracker); view.root() } fn update(&mut self, msg: AppMsg) { match msg { AppMsg::Increment => { self.counter += 1; self.tracker += 1; } } } } impl AppModel { fn view(counter: i32, tracker: i32) -> impl relm4::ViewWidget { let vbox = gtk::Box::builder() .orientation(gtk::Orientation::Vertical) .build(); let label = gtk::Label::new(Some(&format!("Clicked {} times", counter))); vbox.append(&label); let button = gtk::Button::with_label("Click me!"); vbox.append(&button); // This will only update the label if the counter has changed. let view = Self::view(counter, tracker); view.button.set_label(&format!("Clicked {} times", counter)); // This will only update the label if the tracker has changed. #[track = "model.tracker > 0"] view.button.set_label(&format!("Clicked {} times", counter)); button.connect_clicked(view.sender().tx().clone(), |_| AppMsg::Increment); AppModelView { label, button, vbox } } } fn main() { let mut app = relm4::RelmApp::::new(); app.setStyleSheet( ".identical { background-color: #ff0000; }" ); app.run(App::init()); } ``` -------------------------------- ### Tracker Crate Macro Usage Example Source: https://github.com/relm4/book/blob/main/src/efficient_ui/tracker.md Demonstrates the basic usage of the `#[tracker::track]` macro for a Rust struct. It shows how to initialize a struct with a tracker, set fields, check for changes using `changed()`, and reset the tracker. The macro automatically generates methods for field access and change detection. ```rust #[tracker::track] struct Test { x: u8, y: u64, } fn main() { let mut t = Test { x: 0, y: 0, // the macro generates a new variable called // "tracker" which stores the changes tracker: 0, }; t.set_x(42); // let's check whether the change was detected assert!(t.changed(Test::x())); // reset t so we don't track old changes t.reset(); t.set_x(42); // same value, so no change assert!(!t.changed(Test::x())); } ``` -------------------------------- ### Complete Relm4 Application with Widget Templates Source: https://github.com/relm4/book/blob/main/src/widget_templates/index.md This comprehensive Rust code block presents a full Relm4 application example that utilizes widget templates. It includes the definition of custom templates, their integration into a component, and the logic for dynamic updates, showcasing the practical application of widget templating for UI development. ```rust #[macro_use] extern crate relm4; use relm4::prelude::*; // Define a custom box template impl_widget_template! { struct CustomBox<"gtk::Box"> { margin = 5, "css-name" = "custom-box", child_label: gtk::Label = gtk::Label { label: "Initial Label", ..Default::default() } } } // Define a spinning spinner template impl_widget_template! { struct SpinningSpinner<"gtk::Spinner"> { spinning = true, } } // Define the main application component #[relm4::component] struct App { counter: i32, } #[relm4::component] impl SimpleComponent for App { type Init = (); type Input = (); type Output = (); view! { // Use the CustomBox template custom_box = CustomBox { // Access and update the template child #[template_child] child_label = gtk::Label { // Use #[watch] to update the label's text #[watch] label = &format!("Counter: {}", self.counter) } } // Use the SpinningSpinner template spinning_spinner = SpinningSpinner { // You can also set properties directly // Example: Set a specific size if needed // size_request = (50, 50) } // Add other widgets as needed gtk::Button { label = "Increment"; connect_clicked[weak self] => move |_| self.sender().send(AppMsg::Increment).unwrap_or_default(); } } fn init( _init: Self::Init, root: Self::Root, sender: ComponentSender, ) -> ComponentParts { let model = App { counter: 0 }; let widgets = view_output!(); ComponentParts { model, widgets, } } fn update(&mut self, msg: Self::Input, _sender: ComponentSender) { match msg { // Handle messages if any, e.g., AppMsg::Increment => self.counter += 1, } } } fn main() { let app = App::builder().launch(()).sized_default(); app.run(); } ``` -------------------------------- ### GitHub Actions CI Workflow for Relm4 App Source: https://github.com/relm4/book/blob/main/src/continuous_integration.md A GitHub Actions workflow configuration in YAML to automate the build and test process for a Relm4 application. It utilizes the ghcr.io/gtk-rs/gtk4-rs/gtk4:latest container image for building and testing, ensuring compatibility with recent GNOME and GTK versions. This setup requires the `actions/checkout@v3` and `actions-rs/toolchain@v1` actions. ```yaml name: Rust on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: build: runs-on: ubuntu-latest container: image: ghcr.io/gtk-rs/gtk4-rs/gtk4:latest # TODO enable minor version tags / pinning steps: - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable - name: Build run: cargo build - name: Test run: cargo test ``` -------------------------------- ### Relm4 Tracker Example with Rust Source: https://context7.com/relm4/book/llms.txt This Rust code snippet demonstrates how to use the `tracker` crate with Relm4 for optimized UI updates. It shows how to apply the `#[tracker::track]` macro to the `AppModel` struct and use the `#[track]` attribute within the `view!` macro to conditionally update GTK widgets based on model field changes. The `update` function utilizes setters generated by the tracker macro to ensure changes are registered and the `main` function initializes the RelmApp and applies global CSS. ```rust use gtk::prelude::{BoxExt, ButtonExt, OrientableExt}; use rand::prelude::IteratorRandom; use relm4::{gtk, ComponentParts, ComponentSender, RelmApp, RelmWidgetExt, SimpleComponent}; const ICON_LIST: &[&str] = &[ "bookmark-new-symbolic", "edit-copy-symbolic", "starred-symbolic", ]; fn random_icon_name() -> &'static str { ICON_LIST.iter().choose(&mut rand::rng()).unwrap() } // Apply tracker macro to auto-generate change tracking #[tracker::track] struct AppModel { first_icon: &'static str, second_icon: &'static str, identical: bool, } #[derive(Debug)] enum AppInput { UpdateFirst, UpdateSecond, } #[relm4::component] impl SimpleComponent for AppModel { type Init = (); type Input = AppInput; type Output = (); view! { #[root] gtk::ApplicationWindow { // Only update CSS class when 'identical' field changes #[track = "model.changed(AppModel::identical())"] set_class_active: ("identical", model.identical), gtk::Box { set_orientation: gtk::Orientation::Horizontal, set_spacing: 10, gtk::Box { set_orientation: gtk::Orientation::Vertical, gtk::Image { set_pixel_size: 50, // Only update icon when first_icon changes #[track = "model.changed(AppModel::first_icon())"] set_icon_name: Some(model.first_icon), }, gtk::Button { set_label: "Randomize", connect_clicked[sender] => move |_| { sender.input(AppInput::UpdateFirst) } } }, gtk::Box { set_orientation: gtk::Orientation::Vertical, gtk::Image { set_pixel_size: 50, #[track = "model.changed(AppModel::second_icon())"] set_icon_name: Some(model.second_icon), }, gtk::Button { set_label: "Randomize", connect_clicked[sender] => move |_| { sender.input(AppInput::UpdateSecond) } } }, } } } fn init(_: (), root: Self::Root, sender: ComponentSender) -> ComponentParts { let model = AppModel { first_icon: random_icon_name(), second_icon: random_icon_name(), identical: false, tracker: 0, // Required field generated by tracker macro }; let widgets = view_output!(); ComponentParts { model, widgets } } fn update(&mut self, message: Self::Input, _sender: ComponentSender) { self.reset(); // Reset tracker at start of each update match message { AppInput::UpdateFirst => { self.set_first_icon(random_icon_name()); // Use setter to track changes } AppInput::UpdateSecond => { self.set_second_icon(random_icon_name()); } } self.set_identical(self.first_icon == self.second_icon); } } fn main() { let app = RelmApp::new("relm4.test.tracker"); relm4::set_global_css(".identical { background: #00ad5c; }"); app.run::(()); } ``` -------------------------------- ### Complete Relm4 Example for Nested Elements Source: https://github.com/relm4/book/blob/main/src/widget_templates/accessing_nested_template_elements.md This comprehensive Rust code snippet presents the complete example for accessing nested template elements in Relm4. It includes the definitions for the main window, nested pages, and the event handling logic, providing a full context for the feature. ```rust // ... (full code from example) // This would include the template definitions for MainWindow, SettingsPage, HomePage // and the ComponentController implementation with widget initialization and event handling. // For brevity, the full code is omitted here but is available in the referenced file. // Example snippet of event handling: // self.widgets.main_window.settings_page.btn_dark_mode.connect_clicked(|_| { // println!("Dark mode button clicked!"); // }); ``` -------------------------------- ### Initialize Main Application Component (Rust) Source: https://github.com/relm4/book/blob/main/src/components.md Initializes the main application component, constructing child components and forwarding their inputs and outputs. Demonstrates using `launch` and `forward` methods. ```rust impl AppModel { fn init_app() -> ComponentParts { let model = AppModel { mode: AppMode::Normal, header_bar_controller: HeaderBar::builder() .launch(AppMsgIn::SetMode(AppMode::Settings)) // Example input .forward(AppMsgIn::SetMode), // Forward output to AppMsgIn dialog_controller: Dialog::builder() .launch(DialogMsg::Response(Response::Ok)) // Example input .forward(AppMsgIn::Close), // Forward output to AppMsgIn }; let widgets = view_components! { // ... header bar and dialog widgets ... }; ComponentParts { model, widgets, } } } ``` -------------------------------- ### Complete Relm4 Application Code (Rust) Source: https://github.com/relm4/book/blob/main/src/components.md The complete code for a Relm4 application, integrating all previously defined components and logic. This serves as a full example of component composition. ```rust // This is a placeholder for the complete code example. // The actual code would include all the definitions and implementations from the preceding sections. // For brevity, the full code is omitted here, but it would typically be found in a file like `examples/components.rs`. // Example structure: // mod dialog; // mod header_bar; // mod main_app; // // use dialog::{Dialog, DialogMsg, DialogOutput, Response}; // use header_bar::{HeaderBar, HeaderBarMsg}; // use main_app::{AppModel, AppMode, AppMsgIn}; // // fn main() { // let app = RelmApp::::new(); // app.run(); // } ``` -------------------------------- ### Main Function to Run Relm4 Application in Rust Source: https://github.com/relm4/book/blob/main/src/efficient_ui/factory.md Provides the main function required to launch and run the Relm4 application. This function sets up the application and starts the event loop. ```rust fn main() { Application::run::(Default::default()).expect("Failed to run application"); } ``` -------------------------------- ### Construct Widgets with Constructor Methods Source: https://github.com/relm4/book/blob/main/src/component_macro/reference.md Illustrates how to construct widgets using their specific constructor methods when a `Default` implementation is not available or convenient. This involves calling the constructor directly followed by curly braces for configuration. ```rust // Constructor method gtk::Label::new(Some("Label from constructor method")) { /* ... */ } ``` -------------------------------- ### Manual View Logic (Pre-View) Source: https://github.com/relm4/book/blob/main/src/component_macro/reference.md Provides a hook to insert custom code that executes *before* the macro-generated view code. This allows for setup or modifications prior to the main view rendering. ```rust fn pre_view() { // ... } ``` -------------------------------- ### Initialize Root Window in Relm4 Component (Rust) Source: https://github.com/relm4/book/blob/main/src/first_app.md This function, `init_root`, is responsible for creating and returning the outermost widget of the application. For the main component, this must be a `Window` widget. ```rust {{#include ../examples/simple_manual.rs:init_root }} ``` -------------------------------- ### Run Relm4 Application in Rust Source: https://github.com/relm4/book/blob/main/src/first_app.md This code snippet shows how to initialize and run a Relm4 application. It involves creating an instance of the application's model and passing it to `RelmApp::new()`. ```rust {{#include ../examples/simple_manual.rs:main }} ``` -------------------------------- ### Implement View Update for Relm4 Component (Rust) Source: https://github.com/relm4/book/blob/main/src/first_app.md The `update_view` function modifies the UI to reflect changes in the model. This example shows how to update a label's text based on the current value of the counter in the model. ```rust {{#include ../examples/simple_manual.rs:view }} ``` -------------------------------- ### Initialize UI and Model in Relm4 Component (Rust) Source: https://github.com/relm4/book/blob/main/src/first_app.md The `init` function initializes the application's UI and model. It receives the root window and initialization variables, and is responsible for creating the necessary widgets and setting up the initial state of the model. ```rust {{#include ../examples/simple_manual.rs:init }} ``` -------------------------------- ### Define Inbox Enum for Input Messages (Rust) Source: https://github.com/relm4/book/blob/main/src/basic_concepts/messages/input.md Defines an enum named 'Inbox' to represent different types of input messages a component can receive. This example shows a 'GetEmail' variant that carries an 'Email' struct. ```rust enum Inbox { GetEmail(Email), } ``` -------------------------------- ### Construct Widgets using Builder Pattern Source: https://github.com/relm4/book/blob/main/src/component_macro/reference.md Explains how to use the builder pattern for widget construction, which is common for widgets with multiple configuration options. This involves calling `.builder()`, chaining configuration methods, and finally calling `.build()`. ```rust // Builder pattern gtk::Label::builder() .label("Label from builder pattern") .selectable(true) .build() { /* ... */ } ``` -------------------------------- ### Implement FactoryComponent Trait for Relm4 Counters Source: https://github.com/relm4/book/blob/main/src/efficient_ui/factory.md Shows the start of the `FactoryComponent` trait implementation for the `Counter` model in Relm4. It includes the necessary `#[relm4::factory]` attribute macro and associated types like `Init`, `Input`, `Output`, `CommandOutput`, and `ParentWidget`. ```rust #[relm4::factory] #[derive(Debug)] struct CounterView { value: u8, } #[relm4::async_component] impl SimpleComponent for CounterView { type Init = u8; type Input = FactoryInput; type Output = FactoryOutput; view! { // the view of the component } fn init( init: Self::Init, root: Self::Root, sender: ComponentSender, ) -> ComponentParts { let model = CounterView { value: init }; // the view let counter_widget = gtk::Box::builder() .rows(1) .spacing(5) .center_widget(gtk::Label::new(Some(&model.value.to_string()))) .build(); let controller = CounterViewController { value: model.value, sender, counter_widget: counter_widget.clone().downcast().unwrap(), }; ComponentParts { model, view: controller, } } } ``` -------------------------------- ### Async Component Initialization in Rust Source: https://github.com/relm4/book/blob/main/src/threads_and_async/async.md Demonstrates the basic structure for initializing an asynchronous component in Rust using Relm4. It shows the `async` parameter for the `component` macro and the use of `AsyncComponent` trait. ```rust #[relm4::component(async)] impl AsyncComponent for App { type Init = (); type Input = AppMsg; type Output = (); type CommandOutput = (); view! { // ... view definition ... } async fn init( _init: Self::Init, root: Self::Root, sender: ComponentSender, ) -> AsyncComponentParts { // ... initialization logic ... let model = App {}; let parts = ComponentParts { model, view: view! { // ... view widgets ... }, }; AsyncComponentParts { // ... parts ... } } } ``` -------------------------------- ### Handle Input Messages in Update Function (Rust) Source: https://github.com/relm4/book/blob/main/src/basic_concepts/messages/input.md Demonstrates how to handle incoming messages within a component's 'update' function using a match statement. This example processes the 'GetEmail' message by adding the received email to a list. ```rust fn update(&mut self, message: Self::Input, ...) { match message { Inbox::GetEmail(email) => self.emails.push(email) } } ``` -------------------------------- ### Initialize Widgets using View Macro and Local References in Rust Source: https://github.com/relm4/book/blob/main/src/efficient_ui/factory.md Illustrates how to use the `view` macro to initialize widgets, including the use of `#[local_ref]` to access a local variable (counter_box) defined earlier. This allows for convenient initialization of the model with its FactoryVecDeque. ```rust @view fn view(&self, counter_box: &FactoryVecDeque) -> impl IntoElement { gtk::Box::builder() .child(self.widgets.counter_box.clone()) .child(gtk::Button::with_label("Increment").on_click({ let sender = self.sender().clone(); move |_| { sender.send(AppMsg::Increment).unwrap(); } })) .into_element() } ``` -------------------------------- ### Relm4 App: Icon Generation and Uniqueness Source: https://github.com/relm4/book/blob/main/src/efficient_ui/tracker.md Provides Rust functions for generating random icon names from the GTK icon theme and ensuring that newly generated icon names are unique and do not match the current icon. This is a utility for the Relm4 tracker example. ```rust // Placeholder for actual icon generation code from the example // This would typically involve interacting with GTK's icon theme system // and ensuring uniqueness. The actual implementation is omitted here for brevity // but is available in the referenced example file. ``` -------------------------------- ### Construct Widgets with Regular Functions Source: https://github.com/relm4/book/blob/main/src/component_macro/reference.md Demonstrates using regular functions to construct widgets within the `view!` macro. It highlights the potential need to explicitly specify the widget type for macro code generation purposes. ```rust set_property_name = new_box() -> gtk::Box { ... } ``` -------------------------------- ### Relm4 #[track] Attribute Macro Expansion Example Source: https://github.com/relm4/book/blob/main/src/efficient_ui/tracker.md This Rust code snippet shows the approximate macro expansion of a method call annotated with the `#[track]` attribute in Relm4. It demonstrates how the attribute conditionally calls a widget method based on a model's state change. ```rust if model.changed(AppModel::identical()) { self.main_window.set_class_active("identical", model.identical); } ``` -------------------------------- ### Initialize Child Components in App (Rust) Source: https://github.com/relm4/book/blob/main/src/child_components.md Shows the initialization process for child components within the parent application's `init` method. It utilizes the builder pattern and forwards messages from the child component to the parent. ```rust let alert_config = AlertConfig { title: "Alert!".to_string(), message: "Counter reached 42!".to_string(), }; let alert = AlertComponent::builder() .launch(alert_config) .forward(self.sender(), |response| AppMsg::AlertResponse(response)); ``` -------------------------------- ### Spawn and Handle Synchronous Command in Rust Source: https://github.com/relm4/book/blob/main/src/threads_and_async/commands.md Shows how to spawn a synchronous command using `spawn_oneshot_command()` for CPU-bound or blocking I/O tasks. The task is passed as a closure or function pointer. ```rust fn synchronous_task() -> CommandMsg { // Simulate a synchronous task std::thread::sleep(std::time::Duration::from_secs(1)); CommandMsg } #[relm4::component] impl SimpleComponent for App { // ... other fields ... fn update(&mut self, msg: Self::Input, sender: ComponentSender) { // Spawn the synchronous command sender.spawn_oneshot_command(synchronous_task); } fn update_cmd(&mut self, msg: Self::CommandOutput, _sender: ComponentSender) { // Process the command output match msg { CommandMsg => { // Handle the CommandMsg } } } } ``` -------------------------------- ### Derive Macro for Relm4 Components Source: https://github.com/relm4/book/blob/main/src/migrations/0_2_to_0_4.md Demonstrates the usage of the `#[derive(relm4::Components)]` macro for simplifying component management in Relm4. This macro automatically handles the initialization and access of child components, reducing boilerplate code. It defaults to using `RelmWorker::with_new_thread()` for worker threads. ```rust #[derive(relm4::Components)] struct AppComponents { header: RelmComponent, dialog: RelmComponent, } ``` -------------------------------- ### Construct Widgets using `Default` in `view!` Source: https://github.com/relm4/book/blob/main/src/component_macro/reference.md Shows the basic syntax for constructing widgets within the `view!` macro by providing the widget type followed by curly braces. This utilizes the widget's `Default` implementation. ```rust view! { gtk::Window { ... } } ``` -------------------------------- ### Relm4 View Macro Syntax Update Source: https://github.com/relm4/book/blob/main/src/migrations/0_4_to_0_5.md Demonstrates the updated syntax for the `view!` macro in Relm4, showcasing the transition from older attribute styles to newer ones like `#[watch]` and `#[wrap(Some)]`. It also shows the change in connecting signals from `connect_toggled(sender)` to `connect_toggled[sender]`. ```rust view! { gtk::HeaderBar { set_title_widget = Some(>k::Box) { append: group = >k::ToggleButton { set_label: watch!(model.label), connect_toggled(sender) => move |btn| { // ... }, }, } } } ``` ```rust view! { gtk::HeaderBar { #[wrap(Some)] set_title_widget = >k::Box { append: group = >k::ToggleButton { #[watch] set_label: model.label, connect_toggled[sender] => move |btn| { // ... }, }, } } } ``` -------------------------------- ### Integrate CLI Arguments with clap in Relm4 Rust Applications Source: https://context7.com/relm4/book/llms.txt Shows how to integrate command-line argument parsing using the `clap` crate into a Relm4 application. It demonstrates filtering arguments for GTK and handling custom arguments like a debug mode flag. ```rust use clap::Parser; use gtk::prelude::GtkWindowExt; use relm4::{gtk, ComponentParts, ComponentSender, RelmApp, SimpleComponent}; struct AppModel { debug_mode: bool, } #[relm4::component] impl SimpleComponent for AppModel { type Init = bool; type Input = (); type Output = (); view! { gtk::Window { set_title: Some("CLI App"), set_default_width: 300, gtk::Label { #[watch] set_label: if model.debug_mode { "Debug Mode ON" } else { "Normal Mode" }, } } } fn init(debug_mode: Self::Init, root: Self::Root, _sender: ComponentSender) -> ComponentParts { let model = AppModel { debug_mode }; let widgets = view_output!(); ComponentParts { model, widgets } } } #[derive(Parser, Debug)] #[command(version, about)] struct Args { /// Enable debug mode #[arg(long)] debug: bool, /// Pass remaining arguments to GTK #[arg(allow_hyphen_values = true, trailing_var_arg = true)] gtk_options: Vec, } fn main() { let args = Args::parse(); // Prepare GTK arguments (include program name) let program_invocation = std::env::args().next().unwrap(); let mut gtk_args = vec![program_invocation]; gtk_args.extend(args.gtk_options); let app = RelmApp::new("relm4.example.cli"); app.with_args(gtk_args).run::(args.debug); } ``` -------------------------------- ### Relm4 SimpleComponent Implementation in Rust Source: https://context7.com/relm4/book/llms.txt Demonstrates a basic Relm4 application using the SimpleComponent trait. It defines the application state (AppModel), messages (AppMsg), and UI structure using the view! macro. The init, update, and main functions show how to initialize, run, and handle user interactions within a Relm4 application. ```rust use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt}; use relm4::{gtk, ComponentParts, ComponentSender, RelmApp, RelmWidgetExt, SimpleComponent}; // Define the application state struct AppModel { counter: u8, } // Define messages that can modify state #[derive(Debug)] enum AppMsg { Increment, Decrement, } #[relm4::component] impl SimpleComponent for AppModel { type Init = u8; // Initialization data type type Input = AppMsg; // Input message type type Output = (); // Output message type (for parent components) // Declarative widget definition using view! macro view! { gtk::Window { set_title: Some("Simple app"), set_default_width: 300, set_default_height: 100, gtk::Box { set_orientation: gtk::Orientation::Vertical, set_spacing: 5, set_margin_all: 5, gtk::Button { set_label: "Increment", connect_clicked => AppMsg::Increment // Send message on click }, gtk::Button::with_label("Decrement") { connect_clicked => AppMsg::Decrement }, gtk::Label { #[watch] // Auto-update when model changes set_label: &format!("Counter: {}", model.counter), set_margin_all: 5, } } } } // Initialize model and widgets fn init( counter: Self::Init, root: Self::Root, sender: ComponentSender, ) -> ComponentParts { let model = AppModel { counter }; let widgets = view_output!(); ComponentParts { model, widgets } } // Handle messages and update state fn update(&mut self, msg: Self::Input, _sender: ComponentSender) { match msg { AppMsg::Increment => self.counter = self.counter.wrapping_add(1), AppMsg::Decrement => self.counter = self.counter.wrapping_sub(1), } } } fn main() { let app = RelmApp::new("relm4.test.simple"); app.run::(0); // Run with initial counter value of 0 } ``` -------------------------------- ### Refactor FactoryComponent to use Builder Pattern in Relm4 Source: https://github.com/relm4/book/blob/main/src/migrations/0_6_to_0_7.md This snippet demonstrates the refactoring of `FactoryComponent`'s `forward_to_parent` logic into the new builder pattern introduced in Relm4 v0.7. It shows how to replace the direct implementation of `forward_to_parent` with a `launch` and `forward` chain within the factory's builder. ```rust #[relm4::component] impl SimpleComponent for App { // ... fn init( counter: Self::Init, root: &Self::Root, sender: ComponentSender, ) -> ComponentParts { let counters = FactoryVecDeque::builder() .launch(gtk::Box::default()) .forward(sender.input_sender(), |output| match output { CounterOutput::SendFront(index) => AppMsg::SendFront(index), CounterOutput::MoveUp(index) => AppMsg::MoveUp(index), CounterOutput::MoveDown(index) => AppMsg::MoveDown(index), }); // ... } } ``` -------------------------------- ### Rust: RSA Key Generation Function Source: https://github.com/relm4/book/blob/main/src/threads_and_async/index.md Demonstrates a CPU-bound operation for generating an RSA key. This function is computationally intensive and can block the main thread if not handled properly. It takes no arguments and returns a string representing the generated key. ```rust fn generate_rsa_key() -> String { // Simulate a long computation std::thread::sleep(std::time::Duration::from_secs(5)); "-----BEGIN RSA PRIVATE KEY-----\n... -----END RSA PRIVATE KEY-----".to_string() } ``` -------------------------------- ### Define Relm4 Messages using Enum in Rust Source: https://github.com/relm4/book/blob/main/src/basic_concepts/messages.md This Rust code snippet demonstrates how to define messages for Relm4 components using an enum. Enums are the most common way to represent messages, allowing for different types of communication between components. This example shows a basic structure for message definition. ```rust enum Msg { Increment, Decrement, UpdateLabel(String), } ``` -------------------------------- ### Async Component Initialization Loading Widgets in Rust Source: https://github.com/relm4/book/blob/main/src/threads_and_async/async.md Illustrates how to define loading widgets for an asynchronous component during its initialization phase in Rust. This provides a visual indicator while the main initialization logic is being processed. ```rust async fn init_loading_widgets(&self, _root: &Self::Root) -> HtmlEscaped { // ... loading widgets definition ... html_escaped! { // ... spinner or other loading indicators ... } } ``` -------------------------------- ### Define CLI Arguments Structure with Clap Derive Source: https://github.com/relm4/book/blob/main/src/cli.md Defines a struct `Args` to hold command-line arguments using clap's derive feature. It includes a field `gtk_options` to capture arguments intended for GTK/Relm4, using `allow_hyphen_values` and `trailing_var_arg` to handle them correctly. This setup prevents conflicts with application-specific arguments. ```rust use clap::Parser; #[derive(Parser)] #[clap(author, version, about, long_about = None)] struct Args { #[clap(skip)] gtk_options: Vec, #[clap(long)] non_gtk_arg: bool, } ``` -------------------------------- ### Generated SimpleComponent Trait Implementation in Rust Source: https://github.com/relm4/book/blob/main/src/component_macro/expansion.md Illustrates the Rust code generated by the `component` macro for the `SimpleComponent` trait implementation. This includes the `init_root` method and other necessary boilerplate. ```rust impl SimpleComponent for App { type Init = (); type Input = AppMsg; type Output = (); fn init_root(&self, _section: &RootSection) { // ... initialization logic ... } // ... other trait methods ... } ``` -------------------------------- ### Spawn and Handle Asynchronous Command in Rust Source: https://github.com/relm4/book/blob/main/src/threads_and_async/commands.md Demonstrates spawning an asynchronous command using `oneshot_command()` and handling its result in the `update` function. The command executes an async web request and returns a CommandMsg. ```rust async fn async_web_request() -> CommandMsg { // Simulate an async web request tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; CommandMsg } #[relm4::component] impl SimpleComponent for App { type Init = (); type Input = (); type Output = (); type CommandOutput = CommandMsg; view! { // ... view definition } fn init_model(_init: Self::Init) -> Self::Input { // ... initialization Input::None } fn update(&mut self, msg: Self::Input, _sender: ComponentSender) { // Spawn the async command _sender.oneshot_command(async_web_request()); } fn update_cmd(&mut self, msg: Self::CommandOutput, _sender: ComponentSender) { // Process the command output match msg { CommandMsg => { // Handle the CommandMsg, e.g., update model } } } } ``` -------------------------------- ### App Component Usage of Alert Component (Rust) Source: https://github.com/relm4/book/blob/main/src/child_components.md Demonstrates how to integrate and use the alert component within a parent application. It shows the necessary steps for managing child component controllers and initializing them using the builder pattern. ```rust struct AppComponent { alert: Controller, } #[derive(Debug, Clone)] enum AppMsg { AlertResponse(gtk::ResponseType), } impl Component for AppComponent { type Model = (); type Components = AlertComponent; type Input = AppMsg; type Output = (); fn init( &mut self, _parent_widgets: &<>.Widgets as Widgets>, _sender: Sender, ) -> ModelController { let alert_config = AlertConfig { title: "Alert!".to_string(), message: "Counter reached 42!".to_string(), }; let alert = AlertComponent::builder() .launch(alert_config) .forward(self.sender(), |response| AppMsg::AlertResponse(response)); let model = (); let controller = ModelController::new(model, AppComponent { alert }); controller } } ```