use crate::data_provider::words::{delete_word, update_word}; use crate::lang::WordData; use crate::navigation::Page::PreviousPage; use crate::navigation::{NavigatedPage, Page}; use crate::styling::*; use crate::word::WordMessage::*; use crate::{AppState, RootMessage}; use iced::widget::button::danger; use iced::widget::{button, column, row, rule, scrollable, text, text_input}; use iced::{Element, Fill, Task}; use std::sync::{Arc, Mutex}; #[derive(Clone)] pub struct WordState { state: Arc>, index: usize, word: WordData, } impl NavigatedPage for WordState { fn navigate(&self, message: &WordMessage) -> Option { if let Back = message { Some(PreviousPage) } else { None } } fn navigated(&mut self) {} fn update(&mut self, message: WordMessage) -> Task { match message { Back => {} Save => { let mut state = self.state.lock().unwrap(); state.dictionary[self.index] = self.word.clone(); update_word(&mut self.word, &state.connection); return Task::done(RootMessage::Word(Back)); } Delete => { let mut state = self.state.lock().unwrap(); state.dictionary.remove(self.index); delete_word(&self.word, &state.connection); return Task::done(RootMessage::Word(Back)); } SetTags(n) => self.word.tags = n, SetKey(n) => { self.word.key = n; } SetValue(n) => { self.word.value = n; } SetAdditional(key, value) => { self.word.additional.insert(key, value.clone()); } AddAdditional(key) => { self.word.additional.insert(key, "".to_string()); } RemoveAdditional(key) => { self.word.additional.remove(key.as_str()); } } Task::none() } fn view(&self) -> Element<'_, WordMessage> { let mut fast_add = row![]; if !self.word.additional.contains_key("reading") { fast_add = fast_add.push( button("Чтение") .style(button::text) .on_press(AddAdditional("reading".to_string())), ); } if !self.word.additional.contains_key("description") { fast_add = fast_add.push( button("Описание") .style(button::text) .on_press(AddAdditional("description".to_string())), ); } if !self.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", &self.word.key).on_input(SetKey), ] .spacing(QUARTER_SPACING), column![ text!("Значение"), text_input("value", &self.word.value).on_input(SetValue), ] .spacing(QUARTER_SPACING), column![ text!("Теги"), text_input("tags", &self.word.tags).on_input(SetTags), ] .spacing(QUARTER_SPACING), rule::horizontal(2), scrollable(fast_add), ]; for more in &self.word.additional { col = col.push(self.get_view_for_more(more)); } back_overlay( column![ col.spacing(DEFAULT_SPACING / 2.0).width(Fill).height(Fill), row![ button("Сохранить").style(jl_button).on_press(Save), button("Удалить").style(danger).on_press(Delete), ] .spacing(DEFAULT_SPACING) ] .spacing(DEFAULT_SPACING) .into(), Back, ) } } impl WordState { pub(crate) fn new(word: WordData, index: usize, state: Arc>) -> WordState { WordState { state, index, word } } } impl WordState { 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 { Save, Back, Delete, SetTags(String), SetKey(String), SetValue(String), AddAdditional(String), RemoveAdditional(String), SetAdditional(String, String), }