One surface. Two sides. Infinite possibilities.
egui_mobius is a Rust framework designed to modularize and separate front-end and back-end logic in Egui applications. It emphasizes clean architecture with seamless communication between UI and business logic, inspired by the continuous, one-sided nature of the Möbius strip.
In traditional Egui applications, UI and backend logic are often tightly coupled. egui_mobius solves this by providing a structured approach to communication between layers, improving maintainability and scalability.
- Clear separation of UI and business logic.
- Flexible command and event processing using
std::mpsc
. - Modular design for cleaner, more maintainable code.
There are multiple crates in the repository, and each example is a crate. One can test out an example by running these steps, in this case the simple_monitor, and just substitute an appropriate example name.
git clone [email protected]:saturn77/egui_mobius.git
cd egui_mobius
cargo build
cd examples
cargo run -p simple_monitor
When using egui_mobius as a library, add the following to your Cargo.toml
:
[dependencies]
egui_mobius = "0.1.0"
egui = "0.31.0"
eframe = { version = "0.31.0", default-features = false, features = [
"default_fonts",
"glow",
"wayland",
] }
Example of sending a command from the UI using the Signal
struct:
if ui.button("First Task").clicked() {
let signal = Signal::new(self.command_sender.clone());
if let Err(e) = signal.send(Command::FirstTask) {
eprintln!("Error sending command: {}", e);
}
}
Example of setting up a Slot
to handle commands:
use egui_mobius::{factory, Command, CommandResult};
fn main() {
// Create a signal-slot pair using the factory method
let (signal, slot) = factory::<Command, CommandResult>();
// Define a handler function for the slot
let handler = |command: Command| {
match command {
Command::FirstTask => {
slot.send(CommandResult::Success("First Task completed!".to_string())).unwrap();
}
Command::SecondTask => {
slot.send(CommandResult::Success("Second Task completed!".to_string())).unwrap();
}
}
};
// Start the slot with the handler
slot.start(handler);
// Example of sending commands
if let Err(e) = signal.send(Command::FirstTask) {
eprintln!("Error sending command: {}", e);
}
if let Err(e) = signal.send(Command::SecondTask) {
eprintln!("Error sending command: {}", e);
}
}
Contributions are welcome! Please fork the repository, create a feature branch, and submit a pull request.
This project is licensed under the MIT License.
For support or questions, open an issue or reach out on GitHub Discussions.