From 4b7f12e487d75055338b645363904fc1a4491cde Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Sat, 18 Feb 2023 10:56:20 +0100 Subject: [PATCH] refactor(dtmm): Use commands instead of notifications --- crates/dtmm/src/main.rs | 4 +- crates/dtmm/src/main_window.rs | 23 ++--- crates/dtmm/src/state.rs | 173 +++++++++++++++------------------ 3 files changed, 90 insertions(+), 110 deletions(-) diff --git a/crates/dtmm/src/main.rs b/crates/dtmm/src/main.rs index 300c6cd..ba3548a 100644 --- a/crates/dtmm/src/main.rs +++ b/crates/dtmm/src/main.rs @@ -18,7 +18,7 @@ use tracing_subscriber::prelude::*; use tracing_subscriber::EnvFilter; use crate::engine::deploy_mods; -use crate::state::{AsyncAction, Delegate, State, COMMAND_FINISH_DEPLOY}; +use crate::state::{AsyncAction, Delegate, State, ACTION_FINISH_DEPLOY}; mod controller; mod engine; @@ -45,7 +45,7 @@ fn work_thread( event_sink .write() .await - .submit_command(COMMAND_FINISH_DEPLOY, (), Target::Auto) + .submit_command(ACTION_FINISH_DEPLOY, (), Target::Auto) .expect("failed to send command"); }), }; diff --git a/crates/dtmm/src/main_window.rs b/crates/dtmm/src/main_window.rs index 3dd37f0..040d796 100644 --- a/crates/dtmm/src/main_window.rs +++ b/crates/dtmm/src/main_window.rs @@ -5,9 +5,10 @@ use druid::widget::{ }; use druid::{lens, Insets, LensExt, Widget, WidgetExt, WindowDesc}; +use crate::state::{ModInfo, PathBufFormatter, State, View, ACTION_ADD_MOD}; use crate::state::{ - ModInfo, PathBufFormatter, State, StateController, View, ACTION_DELETE_SELECTED_MOD, - ACTION_SELECTED_MOD_DOWN, ACTION_SELECTED_MOD_UP, ACTION_SELECT_MOD, COMMAND_START_DEPLOY, + ACTION_DELETE_SELECTED_MOD, ACTION_SELECTED_MOD_DOWN, ACTION_SELECTED_MOD_UP, + ACTION_SELECT_MOD, ACTION_START_DEPLOY, }; use crate::theme; use crate::widget::ExtraWidgetExt; @@ -51,7 +52,7 @@ fn build_top_bar() -> impl Widget { .with_child( Button::new("Deploy Mods") .on_click(|ctx, _state: &mut State, _env| { - ctx.submit_command(COMMAND_START_DEPLOY); + ctx.submit_command(ACTION_START_DEPLOY); }) .disabled_if(|data, _| !data.can_deploy_mods()), ) @@ -83,7 +84,7 @@ fn build_mod_list() -> impl Widget { .lens(lens!((usize, ModInfo), 1).then(ModInfo::enabled)), ) .with_child(Label::raw().lens(lens!((usize, ModInfo), 1).then(ModInfo::name))) - .on_click(|ctx, (i, _info), _env| ctx.submit_notification(ACTION_SELECT_MOD.with(*i))) + .on_click(|ctx, (i, _info), _env| ctx.submit_command(ACTION_SELECT_MOD.with(*i))) }); let scroll = Scroll::new(list) @@ -123,11 +124,11 @@ fn build_mod_details() -> impl Widget { .lens(State::selected_mod); let button_move_up = Button::new("Move Up") - .on_click(|ctx, _state, _env| ctx.submit_notification(ACTION_SELECTED_MOD_UP)) + .on_click(|ctx, _state, _env| ctx.submit_command(ACTION_SELECTED_MOD_UP)) .disabled_if(|state: &State, _env: &druid::Env| !state.can_move_mod_up()); let button_move_down = Button::new("Move Down") - .on_click(|ctx, _state, _env| ctx.submit_notification(ACTION_SELECTED_MOD_DOWN)) + .on_click(|ctx, _state, _env| ctx.submit_command(ACTION_SELECTED_MOD_DOWN)) .disabled_if(|state: &State, _env: &druid::Env| !state.can_move_mod_down()); let button_toggle_mod = Maybe::new( @@ -150,14 +151,11 @@ fn build_mod_details() -> impl Widget { .disabled_if(|info: &Option, _env: &druid::Env| info.is_none()) .lens(State::selected_mod); - let button_add_mod = Button::new("Add Mod").on_click(|_ctx, state: &mut State, _env| { - // TODO: Implement properly - let info = ModInfo::new(); - state.add_mod(info); - }); + let button_add_mod = Button::new("Add Mod") + .on_click(|ctx, _state: &mut State, _env| ctx.submit_command(ACTION_ADD_MOD)); let button_delete_mod = Button::new("Delete Mod") - .on_click(|ctx, _state, _env| ctx.submit_notification(ACTION_DELETE_SELECTED_MOD)) + .on_click(|ctx, _state, _env| ctx.submit_command(ACTION_DELETE_SELECTED_MOD)) .disabled_if(|info: &Option, _env: &druid::Env| info.is_none()) .lens(State::selected_mod); @@ -250,5 +248,4 @@ fn build_window() -> impl Widget { .must_fill_main_axis(true) .with_child(build_top_bar()) .with_flex_child(build_main(), 1.0) - .controller(StateController::new()) } diff --git a/crates/dtmm/src/state.rs b/crates/dtmm/src/state.rs index c963515..e3eb35b 100644 --- a/crates/dtmm/src/state.rs +++ b/crates/dtmm/src/state.rs @@ -3,20 +3,18 @@ use std::sync::Arc; use druid::im::Vector; use druid::text::Formatter; -use druid::widget::Controller; -use druid::{ - AppDelegate, Command, Data, DelegateCtx, Env, Event, EventCtx, Handled, Lens, Selector, Target, - Widget, -}; +use druid::{AppDelegate, Command, Data, DelegateCtx, Env, Handled, Lens, Selector, Target}; use tokio::sync::mpsc::UnboundedSender; -pub const ACTION_SELECT_MOD: Selector = Selector::new("dtmm.action..select-mod"); +pub const ACTION_SELECT_MOD: Selector = Selector::new("dtmm.action.select-mod"); pub const ACTION_SELECTED_MOD_UP: Selector = Selector::new("dtmm.action.selected-mod-up"); pub const ACTION_SELECTED_MOD_DOWN: Selector = Selector::new("dtmm.action.selected-mod-down"); pub const ACTION_DELETE_SELECTED_MOD: Selector = Selector::new("dtmm.action.delete-selected-mod"); -pub const COMMAND_FINISH_DEPLOY: Selector = Selector::new("dtmm.command.finish-deploy"); -pub const COMMAND_START_DEPLOY: Selector = Selector::new("dtmm.command.start-deploy"); +pub const ACTION_START_DEPLOY: Selector = Selector::new("dtmm.action.start-deploy"); +pub const ACTION_FINISH_DEPLOY: Selector = Selector::new("dtmm.action.finish-deploy"); + +pub const ACTION_ADD_MOD: Selector = Selector::new("dtmm.action.add-mod"); #[derive(Copy, Clone, Data, Debug, PartialEq)] pub(crate) enum View { @@ -236,75 +234,6 @@ impl Lens, Vector<(usize, T)>> for IndexedVectorLens { } } -pub struct StateController {} - -impl StateController { - pub fn new() -> Self { - Self {} - } -} - -// TODO: Turn notifications into commands on the AppDelegate -impl> Controller for StateController { - #[tracing::instrument(name = "StateController::event", skip_all)] - fn event( - &mut self, - child: &mut W, - ctx: &mut EventCtx, - event: &Event, - state: &mut State, - env: &Env, - ) { - match event { - Event::Notification(notif) if notif.is(ACTION_SELECT_MOD) => { - ctx.set_handled(); - let index = notif - .get(ACTION_SELECT_MOD) - .expect("notification type didn't match after check"); - - state.select_mod(*index); - } - Event::Notification(notif) if notif.is(ACTION_SELECTED_MOD_UP) => { - ctx.set_handled(); - let Some(i) = state.selected_mod_index else { - return; - }; - - let len = state.mods.len(); - if len == 0 || i == 0 { - return; - } - - state.mods.swap(i, i - 1); - state.selected_mod_index = Some(i - 1); - } - Event::Notification(notif) if notif.is(ACTION_SELECTED_MOD_DOWN) => { - ctx.set_handled(); - let Some(i) = state.selected_mod_index else { - return; - }; - - let len = state.mods.len(); - if len == 0 || i == usize::MAX || i >= len - 1 { - return; - } - - state.mods.swap(i, i + 1); - state.selected_mod_index = Some(i + 1); - } - Event::Notification(notif) if notif.is(ACTION_DELETE_SELECTED_MOD) => { - ctx.set_handled(); - let Some(index) = state.selected_mod_index else { - return; - }; - - state.mods.remove(index); - } - _ => child.event(ctx, event, state, env), - } - } -} - pub(crate) enum AsyncAction { DeployMods(State), } @@ -326,27 +255,81 @@ impl AppDelegate for Delegate { _ctx: &mut DelegateCtx, _target: Target, cmd: &Command, - data: &mut State, + state: &mut State, _env: &Env, ) -> Handled { - if cmd.is(COMMAND_START_DEPLOY) { - if self - .sender - .send(AsyncAction::DeployMods(data.clone())) - .is_ok() - { - data.is_deployment_in_progress = true; - } else { - tracing::error!("Failed to queue action to deploy mods"); - } + match cmd { + cmd if cmd.is(ACTION_START_DEPLOY) => { + if self + .sender + .send(AsyncAction::DeployMods(state.clone())) + .is_ok() + { + state.is_deployment_in_progress = true; + } else { + tracing::error!("Failed to queue action to deploy mods"); + } - Handled::Yes - } else if cmd.is(COMMAND_FINISH_DEPLOY) { - data.is_deployment_in_progress = false; - Handled::Yes - } else { - tracing::debug!("Unknown command: {:?}", cmd); - Handled::No + Handled::Yes + } + cmd if cmd.is(ACTION_START_DEPLOY) => { + state.is_deployment_in_progress = false; + Handled::Yes + } + cmd if cmd.is(ACTION_SELECT_MOD) => { + let index = cmd + .get(ACTION_SELECT_MOD) + .expect("command type matched but didn't contain the expected value"); + + state.select_mod(*index); + Handled::Yes + } + cmd if cmd.is(ACTION_SELECTED_MOD_UP) => { + let Some(i) = state.selected_mod_index else { + return Handled::No; + }; + + let len = state.mods.len(); + if len == 0 || i == 0 { + return Handled::No; + } + + state.mods.swap(i, i - 1); + state.selected_mod_index = Some(i - 1); + Handled::Yes + } + cmd if cmd.is(ACTION_SELECTED_MOD_DOWN) => { + let Some(i) = state.selected_mod_index else { + return Handled::No; + }; + + let len = state.mods.len(); + if len == 0 || i == usize::MAX || i >= len - 1 { + return Handled::No; + } + + state.mods.swap(i, i + 1); + state.selected_mod_index = Some(i + 1); + Handled::Yes + } + cmd if cmd.is(ACTION_DELETE_SELECTED_MOD) => { + let Some(index) = state.selected_mod_index else { + return Handled::No; + }; + + state.mods.remove(index); + Handled::Yes + } + cmd if cmd.is(ACTION_ADD_MOD) => { + // TODO: Implement properly + let info = ModInfo::new(); + state.add_mod(info); + Handled::Yes + } + cmd => { + tracing::debug!("Unknown command: {:?}", cmd); + Handled::No + } } } }