Crate woab[−][src]
Expand description
WoAB (Widgets on Actors Bridge) is a GUI microframework for combining the widgets toolkit GTK with the actors framework Actix. It helps with:
- Running the actors inside the GTK thread, allowing message handlers to interact with the widgets directly.
- Routing GTK signals through the asynchronous runtime, so that the code handling them can proceed naturally to interact with the actors.
- Mapping widgets and signals from Glade XML files to user types.
To use WoAB one would typically create a factories struct using
woab::Factories
and use it dissect the Glade XML file(s). Each field
of the factories struct will be a woab::BuilderFactory
that can:
- Create a widgets struct using
woab::WidgetsFromBuilder
. - Route the signals defined in the builder to Actix handlers using
woab::Signal
messages. - In the Actix handler, match on the signal name (
msg.name()
) and usewoab::params!
to extract the signal parameters.
The factories can then be used to generate the GTK widgets and either connect them to a new
actor which will receive the signals defined in the Glade GTK or connect them to an existing
actor and tag the signals (so that multiple instances can be added - e.g. with GtkListBox
-
and the signal handler can know from which one the event came). The actors receive the signals
as Actix messages, and the Handler
returns the inhibitness decision (if the signal requires
it)
To remove widget-bound actors at runtime, see woab::Remove
.
To synchronize the widgets’ data with a model (or any old Rust values), see
woab::PropSync
.
After initializing GTK and before starting the main loop,
woab::run_actix_inside_gtk_event_loop
must be called.
Do not run the Actix system manually!
use actix::prelude::*; use gtk::prelude::*; #[derive(woab::Factories)] struct Factories { // The field name must be the ID from the builder XML file: main_window: woab::BuilderFactory, // Possibly other things from the builder XML file that need to be created during the program. } struct AppActor { widgets: AppWidgets, factories: std::rc::Rc<Factories>, // for creating more things from inside the actor. // More actor data } impl actix::Actor for AppActor { type Context = actix::Context<Self>; } #[derive(woab::WidgetsFromBuilder)] struct AppWidgets { main_window: gtk::ApplicationWindow, // needed for making the window visible // Other widgets inside the window to interact with. } impl actix::Handler<woab::Signal> for AppActor { type Result = woab::SignalResult; fn handle(&mut self, msg: woab::Signal, ctx: &mut <Self as actix::Actor>::Context) -> Self::Result { Ok(match msg.name() { // These are custom signals defined in Glade's "Signals" tab. "sig1" => { // Behavior for sig1. None // GTK does not expect sig1 to return anything }, "sig2" => { let woab::params!(text_buffer: gtk::TextBuffer, _) = msg.params()?; // Behavior for sig2 that uses the signal parameters. Some(gtk::Inhibit(false)) // GTK expects sig2 to return its inhibitness decision }, _ => msg.cant_handle()?, }) } } fn main() -> Result<(), Box<dyn std::error::Error>> { let factories = std::rc::Rc::new(Factories::read(read_builder_xml())?); gtk::init()?; woab::run_actix_inside_gtk_event_loop(); // <===== IMPORTANT!!! factories.main_window.instantiate().connect_with(|bld| { let widgets: AppWidgets = bld.widgets().unwrap(); widgets.main_window.show_all(); // Could also be done inside the actor AppActor { widgets, factories: factories, }.start() }); gtk::main(); Ok(()) }
Pitfalls
- When starting Actix actors from outside Tokio/Actix,
woab::block_on
must be used. This is a limitation of Actix that needs to be respected. dialog.run()
must not be used - usewoab::run_dialog
instead.- If an actor is created inside a
gtk::Application::connect_activate
, itsstarted
method will run after theactivate
signal is done. This can be a problem for methods likeset_application
that can segfault if they are called outside theactivate
signal. A solution could be to either do the startup insideconnect_activate
or usewoab::route_signal
to route the application’sactivate
signal to the actor and do the startup in the actor’s signal handler.
Modules
Macros
Helper macro for extracting signal parameters from woab::Signal
.
Structs
Context for utilizing a gtk::Builder
and connecting it to he Actix world.
Degraded version of BuilderConnector
that can only be used to get widgets.
Holds instructions for generating a GTK builder.
Signal
A message for removing actors along with their GUI
The generic signal WoAB uses.
When a future cannot be woken.
Enums
Functions
Run a feature inside the Actix system GTK will be spinning.
Shut down the Actix System
that runs inside the GTK thread.
Run a future outside the Actix runtime.
Route a GIO action to an Actix actor that can handle woab::Signal
.
Route a GTK signal to an Actix actor that can handle woab::Signal
.
Start an Actix System
that runs inside the GTK thread.
Run a GTK dialog and get its response.
Run a future outside the Actix system.
Run a feature inside the Actix system GTK will be spinning.
Asynchronously wait for something to happen somewhere.
Asynchronously wait for a signal to be called.
Type Definitions
Type of a gtk signal callback function that operates on uncast glib values.
Result type for Actix handlers that handle woab::Signal
.
Derive Macros
Dissect a single Glade XML file to multiple builder factories.
Generate methods for setting/getting the widgets’ data.
Make the actor remove itself and its widgets when it gets the woab::Remove
message.
Represent a set of GTK widgets created by a GTK builder.