use crate::app::AppState; use crate::data::entities::{EntityHandle, WordData}; use crate::data::repositories::Repository; use crate::pages::word::WordMessage::*; use crate::styling::*; use iced::widget::button::danger; use iced::widget::space::horizontal; use iced::widget::{button, column, row, rule, scrollable, text, text_input}; use iced::{Element, Fill}; pub struct WordEditor { state: AppState, handle: EntityHandle, on_delete: Option, on_edit: Option, } impl WordEditor { pub(crate) fn update(&mut self, message: WordMessage) -> Option { let dictionary = &mut self.state.dictionary.write(); let word = dictionary.get_mut(&mut self.handle).unwrap(); match message { Delete => { return self.on_delete.take(); } SetTags(n) => word.tags = n, SetKey(n) => { word.key = n; } SetValue(n) => { word.value = n; } SetAdditional(key, value) => { word.additional.insert(key, value.clone()); } AddAdditional(key) => { word.additional.insert(key, "".to_string()); } RemoveAdditional(key) => { word.additional.remove(key.as_str()); } } self.on_edit.take() } pub(crate) fn view(&self) -> Element<'_, WordMessage> { let mut fast_add = row![]; let word = self.state.dictionary.read().get_static(self.handle).unwrap(); if !word.additional.contains_key("reading") { fast_add = fast_add.push( button("Чтение") .style(button::text) .on_press(AddAdditional("reading".to_string())), ); } if !word.additional.contains_key("description") { fast_add = fast_add.push( button("Описание") .style(button::text) .on_press(AddAdditional("description".to_string())), ); } if !word.additional.contains_key("context") { fast_add = fast_add.push( button("В контексте") .style(button::text) .on_press(AddAdditional("context".to_string())), ); } let mut col = iced::widget::column![ column![ text!("Ключ"), text_input("key", &word.key).on_input(SetKey), ] .spacing(QUARTER_SPACING), column![ text!("Значение"), text_input("value", &word.value).on_input(SetValue), ] .spacing(QUARTER_SPACING), column![ text!("Теги"), text_input("tags", &word.tags).on_input(SetTags), ] .spacing(QUARTER_SPACING), rule::horizontal(2), scrollable(fast_add), ]; for more in &word.additional { col = col.push(self.get_view_for_more(more)); } column![ col.spacing(DEFAULT_SPACING / 2.0).width(Fill).height(Fill), row![ horizontal().width(Fill), button("Удалить").style(danger).on_press(Delete), ] .spacing(DEFAULT_SPACING) ] .spacing(DEFAULT_SPACING).into() } } impl WordEditor { pub fn new(handle: EntityHandle, state: AppState) -> Self { Self { state, handle, on_delete: None, on_edit: None } } pub fn on_delete(mut self, message: Message) -> Self { self.on_delete = Some(message); self } pub fn on_edit(mut self, message: Message) -> Self { self.on_edit = Some(message); self } } impl WordEditor { fn get_view_for_more(&self, value: (&String, &String)) -> Element<'_, WordMessage> { match value.0.as_str() { "reading" => self.reading_field(value.1), "description" => self.description_field(value.1), "context" => self.context_field(value.1), _ => self.additional_field(value.1, value.0.clone(), value.0.clone()), } } fn reading_field(&self, value: &str) -> Element<'_, WordMessage> { self.additional_field(value, "Чтение слова".to_string(), "reading".to_string()) } fn description_field(&self, value: &str) -> Element<'_, WordMessage> { self.additional_field(value, "Описание".to_string(), "description".to_string()) } fn context_field(&self, value: &str) -> Element<'_, WordMessage> { self.additional_field(value, "В контексте".to_string(), "context".to_string()) } fn additional_field(&self, value: &str, name: String, id: String) -> Element<'_, WordMessage> { column![ text!("{}", name), row![ text_input(id.clone().as_str(), value) .on_input({ let value = id.clone(); move |string| SetAdditional(value.clone(), string) }) .width(Fill), button("-") .on_press(RemoveAdditional(id.clone())) .style(danger), ] .spacing(QUARTER_SPACING), ] .spacing(QUARTER_SPACING) .into() } } #[derive(Debug, Clone)] pub enum WordMessage { Delete, SetTags(String), SetKey(String), SetValue(String), AddAdditional(String), RemoveAdditional(String), SetAdditional(String, String), }