Added internal messaging and workers to handle per toolbx settings, actual settings handling still missing

This commit is contained in:
2022-08-05 12:47:48 +02:00
parent 48cbc506e2
commit 5049762167
11 changed files with 171 additions and 18 deletions

View File

@@ -1,5 +1,6 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use relm4::gtk::{Application, ApplicationWindow};
use relm4::{factory::FactoryVecDeque, RelmApp}; use relm4::{factory::FactoryVecDeque, RelmApp};
use toolbx::ToolbxContainer; use toolbx::ToolbxContainer;
use ui::app::model::AppModel; use ui::app::model::AppModel;

View File

@@ -5,7 +5,7 @@ use crate::toolbx::ToolbxContainer;
use super::model::ToolbxEntry; use super::model::ToolbxEntry;
pub enum AppMsg { pub enum AppMsg {
ShowToolboxSettingsRequest, ShowToolboxSettingsRequest(DynamicIndex),
ShowToolboxAppsRequest, ShowToolboxAppsRequest,
ToolbxListUpdate(Vec<ToolbxContainer>), ToolbxListUpdate(Vec<ToolbxContainer>),
ToolbxContainerToggleStartStop(DynamicIndex), ToolbxContainerToggleStartStop(DynamicIndex),

View File

@@ -33,7 +33,8 @@ impl FactoryPrototype for ToolbxEntry {
type Msg = AppMsg; type Msg = AppMsg;
fn init_view(&self, key: &DynamicIndex, sender: Sender<Self::Msg>) -> Self::Widgets { fn init_view(&self, key: &DynamicIndex, sender: Sender<Self::Msg>) -> Self::Widgets {
let index = key.clone(); let index_terminal = key.clone();
let index_settings = key.clone();
view! { view! {
suffix_box = &gtk::Box{ suffix_box = &gtk::Box{
@@ -60,7 +61,7 @@ impl FactoryPrototype for ToolbxEntry {
set_tooltip_text: Some(TERMINAL_TOOLTIP), set_tooltip_text: Some(TERMINAL_TOOLTIP),
set_css_classes: &["flat"], set_css_classes: &["flat"],
connect_clicked(sender) => move |btn| { connect_clicked(sender) => move |btn| {
send!(sender, AppMsg::OpenToolbxTerminal(index.clone())); send!(sender, AppMsg::OpenToolbxTerminal(index_terminal.clone()));
}, },
} }
}, },
@@ -73,7 +74,7 @@ impl FactoryPrototype for ToolbxEntry {
set_tooltip_text: Some(SETTINGS_TOOLTIP), set_tooltip_text: Some(SETTINGS_TOOLTIP),
set_css_classes: &["circular"], set_css_classes: &["circular"],
connect_clicked(sender) => move |btn| { connect_clicked(sender) => move |btn| {
send!(sender, AppMsg::ShowToolboxSettingsRequest); send!(sender, AppMsg::ShowToolboxSettingsRequest(index_settings.clone()));
}, },
}, },
} }

View File

@@ -15,11 +15,15 @@ use super::{messages::AppMsg, model::AppModel, workers::AsyncHandlerMsg};
impl AppUpdate for AppModel { impl AppUpdate for AppModel {
fn update(&mut self, msg: AppMsg, components: &AppComponents, _sender: Sender<AppMsg>) -> bool { fn update(&mut self, msg: AppMsg, components: &AppComponents, _sender: Sender<AppMsg>) -> bool {
match msg { match msg {
AppMsg::ShowToolboxSettingsRequest => { AppMsg::ShowToolboxSettingsRequest(index) => {
components if let Some(toolbx_entry) = self.toolboxes.get(index.current_index()) {
.toolbox_settings_dialog components
.send(ToolboxSettingsDialogMsg::Show) .toolbox_settings_dialog
.unwrap(); .send(ToolboxSettingsDialogMsg::Show(
toolbx_entry.toolbx_container.clone(),
))
.unwrap();
}
} }
AppMsg::ShowToolboxAppsRequest => { AppMsg::ShowToolboxAppsRequest => {
components components

View File

@@ -0,0 +1,11 @@
use relm4::RelmComponent;
use relm4::RelmMsgHandler;
use relm4::Sender;
use super::model::ToolboxSettingsDialogModel;
use crate::ui::components::toolbox_settings::workers::AsyncSettingsHandler;
#[derive(relm4::Components)]
pub struct SettingsComponents {
pub async_handler: RelmMsgHandler<AsyncSettingsHandler, ToolboxSettingsDialogModel>,
}

View File

@@ -1,4 +1,9 @@
use crate::toolbx::ToolbxContainer;
use super::model::ToolboxPreferences;
pub enum ToolboxSettingsDialogMsg { pub enum ToolboxSettingsDialogMsg {
Show, Show(ToolbxContainer),
ReplyToolbxSettings(ToolboxPreferences),
Close, Close,
} }

View File

@@ -1,4 +1,6 @@
pub mod components;
pub mod messages; pub mod messages;
pub mod model; pub mod model;
pub mod update; pub mod update;
pub mod widgets; pub mod widgets;
pub mod workers;

View File

@@ -1,13 +1,23 @@
use relm4::Model; use relm4::Model;
use super::{messages::ToolboxSettingsDialogMsg, widgets::ToolboxSettingsDialogWidgets}; use super::{
components::SettingsComponents, messages::ToolboxSettingsDialogMsg,
widgets::ToolboxSettingsDialogWidgets,
};
use crate::toolbx::ToolbxContainer;
pub struct ToolboxSettingsDialogModel { pub struct ToolboxSettingsDialogModel {
pub hidden: bool, pub hidden: bool,
pub window_title: Option<String>,
pub current_toolbox_container: Option<ToolbxContainer>,
pub current_toolbx_settings: Option<ToolboxPreferences>,
} }
impl Model for ToolboxSettingsDialogModel { impl Model for ToolboxSettingsDialogModel {
type Msg = ToolboxSettingsDialogMsg; type Msg = ToolboxSettingsDialogMsg;
type Widgets = ToolboxSettingsDialogWidgets; type Widgets = ToolboxSettingsDialogWidgets;
type Components = (); type Components = SettingsComponents;
} }
#[derive(Debug, Clone)]
pub struct ToolboxPreferences {}

View File

@@ -2,23 +2,66 @@ use relm4::{ComponentUpdate, Sender};
use crate::ui::app::{messages::AppMsg, model::AppModel}; use crate::ui::app::{messages::AppMsg, model::AppModel};
use super::{messages::ToolboxSettingsDialogMsg, model::ToolboxSettingsDialogModel}; use super::{
components::SettingsComponents, messages::ToolboxSettingsDialogMsg,
model::ToolboxSettingsDialogModel, workers::AsyncSettingsHandlerMsg,
};
impl ComponentUpdate<AppModel> for ToolboxSettingsDialogModel { impl ComponentUpdate<AppModel> for ToolboxSettingsDialogModel {
fn init_model(_parent_model: &AppModel) -> Self { fn init_model(_parent_model: &AppModel) -> Self {
ToolboxSettingsDialogModel { hidden: true } ToolboxSettingsDialogModel {
hidden: true,
window_title: None,
current_toolbox_container: None,
current_toolbx_settings: None,
}
} }
fn update( fn update(
&mut self, &mut self,
msg: ToolboxSettingsDialogMsg, msg: ToolboxSettingsDialogMsg,
_components: &(), components: &SettingsComponents,
_sender: Sender<ToolboxSettingsDialogMsg>, _sender: Sender<ToolboxSettingsDialogMsg>,
parent_sender: Sender<AppMsg>, parent_sender: Sender<AppMsg>,
) { ) {
match msg { match msg {
ToolboxSettingsDialogMsg::Show => self.hidden = false, ToolboxSettingsDialogMsg::ReplyToolbxSettings(settings) => {
ToolboxSettingsDialogMsg::Close => self.hidden = true, self.current_toolbx_settings = Some(settings);
println!("Received Toolbox Settings");
}
ToolboxSettingsDialogMsg::Show(toolbx_container) => {
self.hidden = false;
self.window_title = Some(format!(
"Toolbx Preferences: {}",
toolbx_container.name.clone()
));
// TODO: create settings handling for each toolbox
// probably settings for a toolbox should be stored in a HashMap and loaded based on that
components
.async_handler
.sender()
.blocking_send(AsyncSettingsHandlerMsg::RequestToolbxSettings(
toolbx_container.clone(),
))
.expect("Receiver dropped");
self.current_toolbox_container = Some(toolbx_container);
}
ToolboxSettingsDialogMsg::Close => {
self.current_toolbx_settings.as_ref().map(|settings| {
components
.async_handler
.sender()
.blocking_send(AsyncSettingsHandlerMsg::SaveToolboxSettings(
settings.clone(),
))
.expect("Receiver dropped");
});
self.hidden = true;
self.window_title = None;
self.current_toolbox_container = None;
self.current_toolbx_settings = None;
}
} }
} }
} }

View File

@@ -24,7 +24,7 @@ use super::model::ToolboxSettingsDialogModel;
impl Widgets<ToolboxSettingsDialogModel, AppModel> for ToolboxSettingsDialogWidgets { impl Widgets<ToolboxSettingsDialogModel, AppModel> for ToolboxSettingsDialogWidgets {
view! { view! {
adw::PreferencesWindow { adw::PreferencesWindow {
set_title: Some("Preferences: <Toolbox_name>"), set_title: watch!{ model.window_title.as_ref().map( |x| x.as_str() ) },
set_transient_for: parent!{Some(&parent_widgets.main_window)}, set_transient_for: parent!{Some(&parent_widgets.main_window)},
set_modal: true, set_modal: true,
set_visible: watch!(!model.hidden), set_visible: watch!(!model.hidden),

View File

@@ -0,0 +1,76 @@
use std::time::Duration;
use crate::toolbx::ToolbxContainer;
use relm4::factory::DynamicIndex;
use relm4::{send, MessageHandler, Sender};
use tokio::runtime::{Builder, Runtime};
use tokio::sync::mpsc::{channel, Sender as TokioSender};
use crate::ui::app::{messages::AppMsg, model::AppModel};
use super::model::ToolboxPreferences;
use crate::ui::components::toolbox_settings::messages::ToolboxSettingsDialogMsg;
use crate::ui::components::ToolboxSettingsDialogModel;
// Code adapted from https://relm4.org/book/stable/message_handler.html
pub struct AsyncSettingsHandler {
_rt: Runtime,
sender: TokioSender<AsyncSettingsHandlerMsg>,
}
#[derive(Debug)]
pub enum AsyncSettingsHandlerMsg {
RequestToolbxSettings(ToolbxContainer),
SaveToolboxSettings(ToolboxPreferences),
}
impl MessageHandler<ToolboxSettingsDialogModel> for AsyncSettingsHandler {
type Msg = AsyncSettingsHandlerMsg;
type Sender = TokioSender<AsyncSettingsHandlerMsg>;
fn init(
_parent_model: &ToolboxSettingsDialogModel,
parent_sender: Sender<ToolboxSettingsDialogMsg>,
) -> Self {
let (sender, mut rx) = channel::<AsyncSettingsHandlerMsg>(10);
let rt = Builder::new_multi_thread()
.worker_threads(1)
.enable_time()
.build()
.unwrap();
rt.spawn(async move {
while let Some(msg) = rx.recv().await {
let parent_sender = parent_sender.clone();
tokio::spawn(async move {
match msg {
AsyncSettingsHandlerMsg::SaveToolboxSettings(tbx_settings) => {
// TODO: actually save settings
println!("Received Toolbx Settings save request");
}
AsyncSettingsHandlerMsg::RequestToolbxSettings(tbx) => {
println!("Received ToolbxSettings Request");
parent_sender
.send(ToolboxSettingsDialogMsg::ReplyToolbxSettings(
ToolboxPreferences {},
))
.unwrap();
}
}
});
}
});
AsyncSettingsHandler { _rt: rt, sender }
}
fn send(&self, msg: Self::Msg) {
self.sender.blocking_send(msg).unwrap();
}
fn sender(&self) -> Self::Sender {
self.sender.clone()
}
}