demo.mp4
-
This project aims at experimenting GUI framework in Rust ecosystem.
-
Iced depends everything in messages, which means that we can apply traditional command/event for the frontend (which is also a pattern in WPF where each button in the XAML file has a "commmand" props).
-
In frontend we can even arrange main app as Root State, and for each subdomain logic we define new
struct
as a separated state, as if it is an redux state management tool.The app listens to messages to execute different action:
// app_slice.rs impl ShellScriptsAppRootState { pub fn update(&mut self, message: Message) -> Task<Message> { match message { Message::DatabaseConnected(db) => { self.db = Some(db.clone()); self.folder_state.folder_script_repository = Some(Arc::new(ScriptFolderRepository::new(db.clone()))); self.folder_state.shell_script_repository = Some(Arc::new(ShellScriptRepository::new(db.clone()))); self.loading = false; println!("Database connected successfully!"); Task::perform(async {}, |_| Message::Folder(FolderMessage::LoadFolders)) } // forward message to subdomain Message::Folder(folder_msg) => { self.folder_state.update(folder_msg).map(Message::Folder) } ... } } } // folder_slice.rs impl FolderState { pub fn update(&mut self, message: FolderMessage) -> Task<FolderMessage> { match message { FolderMessage::SelectFolder(folder) => { self.selected_folder = Some(folder.clone()); Task::perform(async {}, move |_| { FolderMessage::FolderSelected(folder.clone()) }) } FolderMessage::FolderSelected(selected_folder) => { if let Some(repo) = &self.shell_script_repository { let repo = repo.clone(); let folder_id = selected_folder.id; let folder_name = selected_folder.name.clone(); Task::perform( async move { repo.get_all_scripts_of_folder(folder_id) }, move |scripts| { println!( "Loaded {} scripts for folder {}", scripts.len(), folder_name ); FolderMessage::ScriptsLoaded(scripts) }, ) } else { Task::none() } } ... } } }
This app in DEV mode (cargo build
, cargo run
etc) has bound with a dev-database.db
in the project root directory, which will be generated upon the first loading of the app.
In development I usually turn the auto-creation of the tables off and do the schema-migration as if it is a standard backend application.
We have arranged the project so that we use prisma
to compile its schema.prisma
file into Rust entity classes, see the build.rs
for detail.
UI flexibility is very limited. There is no way to create a standard "context-menu" that captures my clicking position
For standard grids Iced is fine, but I am seeking for the most powerful one, so I would stop at this stage and try other framework such as egui
.