diff --git a/Cargo.toml b/Cargo.toml index ecdd742..2f0368d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,11 +8,7 @@ edition = "2021" anyhow = "1.0.75" directories = "5.0.1" iced = { version = "0.10.0", features = ["lazy"] } -iced_aw = { version = "0.7.0", default-features = false, features = [ - "modal", - "card", - "number_input", -] } +iced_aw = { version = "0.7.0", default-features = false, features = ["modal", "card", "number_input", "selection_list"] } itertools = "0.11.0" peg = "0.8.2" serde = { version = "1.0.192", features = ["derive"] } diff --git a/src/main.rs b/src/main.rs index ab108d6..6792bf3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,7 +15,7 @@ use iced::{ }, window, Alignment, Application, Command, Event, Length, Renderer, Settings, Theme, }; -use iced_aw::{card, modal, number_input}; +use iced_aw::{card, modal, number_input, selection_list}; use itertools::Itertools; use serde::{Deserialize, Serialize}; @@ -306,12 +306,90 @@ where } } +struct VariableDelete { + on_delete: F, + options: Vec, +} + +#[derive(Default)] +struct VariableDeleteState { + modal: bool, + value: Option, +} + +#[derive(Debug, Clone)] +enum VariableDeleteMessage { + Open, + Close, + Delete, + Select(String), +} + +impl iced::widget::Component for VariableDelete +where + F: FnMut(String) -> M, +{ + type State = VariableDeleteState; + type Event = VariableDeleteMessage; + + fn update(&mut self, state: &mut Self::State, event: Self::Event) -> Option { + match event { + VariableDeleteMessage::Open => { + state.modal = true; + } + VariableDeleteMessage::Close => { + state.modal = false; + } + VariableDeleteMessage::Select(s) => { + state.value = Some(s); + } + VariableDeleteMessage::Delete => { + if let Some(d) = state.value.take() { + state.modal = false; + return Some((self.on_delete)(d)); + } + } + } + + None + } + + fn view(&self, state: &Self::State) -> iced_aw::Element<'_, Self::Event, Renderer> { + let underlay = button(text("Delete")) + .on_press(VariableDeleteMessage::Open) + .style(theme::Button::Destructive); + let overlay = match state.modal { + true => Some( + card( + "Delete a category", + column![ + selection_list(&self.options, |_, v| VariableDeleteMessage::Select(v)) + .height(Length::Shrink), + button(text("Delete")) + .on_press(VariableDeleteMessage::Delete) + .style(theme::Button::Destructive) + ], + ) + .max_width(300.) + .on_close(VariableDeleteMessage::Close), + ), + false => None, + }; + + modal(underlay, overlay) + .on_esc(VariableDeleteMessage::Close) + .backdrop(VariableDeleteMessage::Close) + .into() + } +} + #[derive(Clone, Debug)] enum VariableMessage { CloseAdd, Add, EditAdd(String), ExprEdit(String, String), + OnDelete(String), DoAdd, } @@ -321,15 +399,17 @@ struct VariableState { add_value: String, } -struct VariableSpendings<'a, F, G> { +struct VariableSpendings<'a, F, G, H> { items: &'a BTreeMap)>, on_add: F, on_expr_edit: G, + on_delete: H, } -impl iced::widget::Component for VariableSpendings<'_, F, G> +impl iced::widget::Component for VariableSpendings<'_, F, G, H> where F: FnMut(String) -> M, + H: FnMut(String) -> M, G: FnMut(String, String) -> M, { type State = VariableState; @@ -354,6 +434,9 @@ where VariableMessage::ExprEdit(name, value) => { return Some((self.on_expr_edit)(name, value)); } + VariableMessage::OnDelete(d) => { + return Some((self.on_delete)(d)); + } } None @@ -363,7 +446,14 @@ where fn view(&self, state: &Self::State) -> iced_aw::Element<'_, Self::Event, Renderer> { let underlay = column![ text("Variable").size(TEXT_H2), - button(text("Add")).on_press(VariableMessage::Add), + row![ + button(text("Add")).on_press(VariableMessage::Add), + component(VariableDelete { + on_delete: VariableMessage::OnDelete, + options: self.items.keys().cloned().collect(), + }) + ] + .spacing(5), horizontal_rule(LIST_RULE), column( self.items @@ -736,6 +826,7 @@ enum Message { AddSaving(String, f64), FontLoaded(Result<(), font::Error>), AddVariable(String), + DeleteVariable(String), EditVariable(String, String), EditEarings1(f64), EditEarings2(f64), @@ -916,6 +1007,9 @@ impl Application for Glaurung { self.edit.init_from(report.clone()) } } + Message::DeleteVariable(d) => { + self.edit.variable.remove(&d); + } } Command::none() @@ -1077,6 +1171,7 @@ impl Application for Glaurung { component(VariableSpendings { items: &self.edit.variable, on_add: Message::AddVariable, + on_delete: Message::DeleteVariable, on_expr_edit: Message::EditVariable, }), horizontal_rule(SECTION_RULE).style(|theme: &Theme| {