parent
bb5a2ecf64
commit
3252e66a3f
4 changed files with 38 additions and 14 deletions
|
@ -78,6 +78,7 @@ pub(crate) struct State {
|
||||||
pub current_view: View,
|
pub current_view: View,
|
||||||
pub mods: Vector<ModInfo>,
|
pub mods: Vector<ModInfo>,
|
||||||
pub selected_mod_index: Option<usize>,
|
pub selected_mod_index: Option<usize>,
|
||||||
|
pub dirty: bool,
|
||||||
pub is_deployment_in_progress: bool,
|
pub is_deployment_in_progress: bool,
|
||||||
pub is_reset_in_progress: bool,
|
pub is_reset_in_progress: bool,
|
||||||
pub is_save_in_progress: bool,
|
pub is_save_in_progress: bool,
|
||||||
|
@ -106,6 +107,7 @@ impl State {
|
||||||
current_view: View::default(),
|
current_view: View::default(),
|
||||||
mods: Vector::new(),
|
mods: Vector::new(),
|
||||||
selected_mod_index: None,
|
selected_mod_index: None,
|
||||||
|
dirty: false,
|
||||||
is_deployment_in_progress: false,
|
is_deployment_in_progress: false,
|
||||||
is_reset_in_progress: false,
|
is_reset_in_progress: false,
|
||||||
is_save_in_progress: false,
|
is_save_in_progress: false,
|
||||||
|
|
|
@ -33,6 +33,8 @@ pub(crate) const ACTION_START_SAVE_SETTINGS: Selector =
|
||||||
pub(crate) const ACTION_FINISH_SAVE_SETTINGS: Selector =
|
pub(crate) const ACTION_FINISH_SAVE_SETTINGS: Selector =
|
||||||
Selector::new("dtmm.action.finish-save-settings");
|
Selector::new("dtmm.action.finish-save-settings");
|
||||||
|
|
||||||
|
pub(crate) const ACTION_SET_DIRTY: Selector = Selector::new("dtmm.action.set-dirty");
|
||||||
|
|
||||||
pub(crate) enum AsyncAction {
|
pub(crate) enum AsyncAction {
|
||||||
DeployMods(State),
|
DeployMods(State),
|
||||||
ResetDeployment(State),
|
ResetDeployment(State),
|
||||||
|
@ -81,6 +83,7 @@ impl AppDelegate<State> for Delegate {
|
||||||
}
|
}
|
||||||
cmd if cmd.is(ACTION_FINISH_DEPLOY) => {
|
cmd if cmd.is(ACTION_FINISH_DEPLOY) => {
|
||||||
state.is_deployment_in_progress = false;
|
state.is_deployment_in_progress = false;
|
||||||
|
state.dirty = false;
|
||||||
Handled::Yes
|
Handled::Yes
|
||||||
}
|
}
|
||||||
cmd if cmd.is(ACTION_START_RESET_DEPLOYMENT) => {
|
cmd if cmd.is(ACTION_START_RESET_DEPLOYMENT) => {
|
||||||
|
@ -226,6 +229,10 @@ impl AppDelegate<State> for Delegate {
|
||||||
|
|
||||||
Handled::Yes
|
Handled::Yes
|
||||||
}
|
}
|
||||||
|
cmd if cmd.is(ACTION_SET_DIRTY) => {
|
||||||
|
state.dirty = true;
|
||||||
|
Handled::Yes
|
||||||
|
}
|
||||||
cmd => {
|
cmd => {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
tracing::warn!("Unknown command: {:?}", cmd);
|
tracing::warn!("Unknown command: {:?}", cmd);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use druid::widget::{Button, Controller, Scroll};
|
use druid::widget::{Button, Controller, Scroll};
|
||||||
use druid::{Data, Env, Event, EventCtx, Rect, UpdateCtx, Widget};
|
use druid::{Data, Env, Event, EventCtx, Rect, UpdateCtx, Widget};
|
||||||
|
|
||||||
use crate::state::{State, ACTION_START_SAVE_SETTINGS};
|
use crate::state::{State, ACTION_SET_DIRTY, ACTION_START_SAVE_SETTINGS};
|
||||||
|
|
||||||
pub struct DisabledButtonController;
|
pub struct DisabledButtonController;
|
||||||
|
|
||||||
|
@ -57,11 +57,16 @@ impl<T: Data, W: Widget<T>> Controller<T, Scroll<T, W>> for AutoScrollController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A controller that submits the command to save settings every time its widget's
|
macro_rules! compare_state_fields {
|
||||||
/// data changes.
|
($old:ident, $new:ident, $($field:ident),+) => {
|
||||||
pub struct SaveSettingsController;
|
$($old.$field != $new.$field) || +
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<W: Widget<State>> Controller<State, W> for SaveSettingsController {
|
/// A controller that tracks state changes for certain fields and submits commands to handle them.
|
||||||
|
pub struct DirtyStateController;
|
||||||
|
|
||||||
|
impl<W: Widget<State>> Controller<State, W> for DirtyStateController {
|
||||||
fn update(
|
fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
child: &mut W,
|
child: &mut W,
|
||||||
|
@ -70,13 +75,14 @@ impl<W: Widget<State>> Controller<State, W> for SaveSettingsController {
|
||||||
data: &State,
|
data: &State,
|
||||||
env: &Env,
|
env: &Env,
|
||||||
) {
|
) {
|
||||||
// Only filter for the values that actually go into the settings file.
|
if compare_state_fields!(old_data, data, mods, game_dir, data_dir) {
|
||||||
if old_data.mods != data.mods
|
|
||||||
|| old_data.game_dir != data.game_dir
|
|
||||||
|| old_data.data_dir != data.data_dir
|
|
||||||
{
|
|
||||||
ctx.submit_command(ACTION_START_SAVE_SETTINGS);
|
ctx.submit_command(ACTION_START_SAVE_SETTINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if compare_state_fields!(old_data, data, mods, game_dir) {
|
||||||
|
ctx.submit_command(ACTION_SET_DIRTY);
|
||||||
|
}
|
||||||
|
|
||||||
child.update(ctx, old_data, data, env)
|
child.update(ctx, old_data, data, env)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::state::{
|
||||||
ACTION_START_RESET_DEPLOYMENT,
|
ACTION_START_RESET_DEPLOYMENT,
|
||||||
};
|
};
|
||||||
use crate::ui::theme;
|
use crate::ui::theme;
|
||||||
use crate::ui::widget::controller::{AutoScrollController, SaveSettingsController};
|
use crate::ui::widget::controller::{AutoScrollController, DirtyStateController};
|
||||||
use crate::ui::widget::PathBufFormatter;
|
use crate::ui::widget::PathBufFormatter;
|
||||||
|
|
||||||
const TITLE: &str = "Darktide Mod Manager";
|
const TITLE: &str = "Darktide Mod Manager";
|
||||||
|
@ -38,11 +38,20 @@ fn build_top_bar() -> impl Widget<State> {
|
||||||
state.current_view = View::Settings;
|
state.current_view = View::Settings;
|
||||||
});
|
});
|
||||||
|
|
||||||
let deploy_button = Button::new("Deploy Mods")
|
let deploy_button = {
|
||||||
|
Button::dynamic(|state: &State, _| {
|
||||||
|
let mut s = String::new();
|
||||||
|
if state.dirty {
|
||||||
|
s.push_str("! ");
|
||||||
|
}
|
||||||
|
s.push_str("Deploy Mods");
|
||||||
|
s
|
||||||
|
})
|
||||||
.on_click(|ctx, _state: &mut State, _env| {
|
.on_click(|ctx, _state: &mut State, _env| {
|
||||||
ctx.submit_command(ACTION_START_DEPLOY);
|
ctx.submit_command(ACTION_START_DEPLOY);
|
||||||
})
|
})
|
||||||
.disabled_if(|data, _| data.is_deployment_in_progress || data.is_reset_in_progress);
|
.disabled_if(|data, _| data.is_deployment_in_progress || data.is_reset_in_progress)
|
||||||
|
};
|
||||||
|
|
||||||
let reset_button = Button::new("Reset Game")
|
let reset_button = Button::new("Reset Game")
|
||||||
.on_click(|ctx, _state: &mut State, _env| {
|
.on_click(|ctx, _state: &mut State, _env| {
|
||||||
|
@ -308,5 +317,5 @@ fn build_window() -> impl Widget<State> {
|
||||||
.with_child(build_top_bar())
|
.with_child(build_top_bar())
|
||||||
.with_flex_child(build_main(), 1.0)
|
.with_flex_child(build_main(), 1.0)
|
||||||
.with_child(build_log_view())
|
.with_child(build_log_view())
|
||||||
.controller(SaveSettingsController)
|
.controller(DirtyStateController)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue