diff --git a/src/main.rs b/src/main.rs index 041b27d..74cba31 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,11 @@ #![feature(iter_map_windows)] use iced::{ - clipboard, widget::{self, button, column, combo_box, row, scrollable::{Direction, Scrollbar}, scrollable, text, text_input}, Element, Length, Task + Element, Length, Task, clipboard, + widget::{ + self, button, column, combo_box, row, scrollable, + scrollable::{Direction, Scrollbar}, + text, text_input, + }, }; use std::{env, fs, path::PathBuf}; use texts::*; @@ -34,19 +39,18 @@ fn main() -> iced::Result { #[derive(Debug, Clone)] enum Message { - BibleSearchInput(String), - BibleSelected(String), - BibleSearchSubmit, - CopyText, - Clear, - WordSearchInput(String), - SubmitWordSearch, - QuickSearch(String), + BibleSearchInput(usize, String), + BibleSelected(usize, String), + BibleSearchSubmit(usize), + CopyText(usize), + Clear(usize), + WordSearchInput(usize, String), + SubmitWordSearch(usize), + QuickSearch(usize, String), AddColRight, } -struct State { - files: combo_box::State, +struct ColState { selected_file: Option, bible_selected: Option, @@ -55,9 +59,29 @@ struct State { word_search: String, word_search_results: Option>, +} +impl Default for ColState { + fn default() -> Self { + Self { + selected_file: None, + bible_selected: None, + + bible_search: String::new(), + scripture_body: None, + + word_search: String::new(), + word_search_results: None, + } + } +} + +struct State { + files: combo_box::State, + states: Vec, cols: usize, } + impl Default for State { fn default() -> Self { let files = if let Ok(contents) = fs::read_dir(BIBLE_DIRECTORY) { @@ -84,15 +108,7 @@ impl Default for State { Self { files: combo_box::State::new(files), - selected_file: None, - bible_selected: None, - - bible_search: String::new(), - scripture_body: None, - - word_search: String::new(), - word_search_results: None, - + states: vec![ColState::default()], cols: 1, } } @@ -101,109 +117,122 @@ impl Default for State { impl State { fn update(&mut self, msg: Message) -> Task { match msg { - Message::AddColRight => self.cols += 1, - Message::BibleSelected(file) => { + Message::AddColRight => { + self.cols += 1; + // clone this state into the new one + // self.states.push(self.states.into_iter().last().unwrap().clone()) + self.states.push(ColState::default()) + } + Message::BibleSelected(i, file) => { if let Ok(contents) = fs::read_to_string(&file) { if let Ok(bible) = quick_xml::de::from_str::(&contents) { // State is held technically in this variable, although // the Bible is held in memory in it's own variable. - self.selected_file = Some(format!("{bible}")); - self.bible_selected = Some(bible); + self.states[i].selected_file = Some(format!("{bible}")); + self.states[i].bible_selected = Some(bible); // automatically focus the search bar when done here - return text_input::focus("bible-search"); + // return text_input::focus("bible-search"); } } } - Message::QuickSearch(s) => { - self.bible_search = s; - return self.update(Message::BibleSearchSubmit); + Message::QuickSearch(i, s) => { + self.states[i].bible_search = s; + return self.update(Message::BibleSearchSubmit(i)); } - Message::BibleSearchInput(query) => self.bible_search = query, - Message::WordSearchInput(query) => self.word_search = query, - Message::BibleSearchSubmit => { - let mut splits = self.bible_search.split_whitespace(); + Message::BibleSearchInput(i, query) => self.states[i].bible_search = query, + Message::WordSearchInput(i, query) => self.states[i].word_search = query, + Message::BibleSearchSubmit(i) => { + let mut splits = self.states[i].bible_search.split_whitespace(); let book = splits.next(); let location = splits.next(); if let (Some(book), Some(chap_and_ver), Some(bible)) = - (book, location, &self.bible_selected) + (book, location, &self.states[i].bible_selected) { - self.scripture_body = bible::get(book, chap_and_ver, vec![bible]); + self.states[i].scripture_body = bible::get(book, chap_and_ver, vec![bible]); } } - Message::SubmitWordSearch => { - if let Some(bible) = &self.bible_selected { - let res = bible::search_for_word(&self.word_search, bible); - self.word_search_results = Some(res); + Message::SubmitWordSearch(i) => { + if let Some(bible) = &self.states[i].bible_selected { + let res = bible::search_for_word(&self.states[i].word_search, bible); + self.states[i].word_search_results = Some(res); } } - Message::CopyText => { - if let Some(text) = &self.scripture_body { + Message::CopyText(i) => { + if let Some(text) = &self.states[i].scripture_body { return clipboard::write::(parse(text)); } } - Message::Clear => { - self.scripture_body = None; - self.word_search_results = None; - self.bible_search = String::new(); - self.word_search = String::new(); - return text_input::focus("bible-search"); + Message::Clear(i) => { + self.states[i].scripture_body = None; + self.states[i].word_search_results = None; + self.states[i].bible_search = String::new(); + self.states[i].word_search = String::new(); + // return text_input::focus("bible-search"); } }; Task::none() } fn view(&self) -> Element { - let body = if let Some(body) = self.scripture_body.clone() { - parse(&body) - } else { - String::new() - }; - - scrollable(row((0..self.cols).map(|_| { - row![ + scrollable(row![ + row((0..self.cols).map(|col_index| { column![ combo_box( &self.files, "Select Bible", - self.selected_file.as_ref(), - Message::BibleSelected + self.states[col_index].selected_file.as_ref(), + move |s| Message::BibleSelected(col_index, s) ), - text_input("Search query, ie: Gen 1:1", &self.bible_search) - .on_input(Message::BibleSearchInput) - .on_submit(Message::BibleSearchSubmit) - .id("bible-search"), - widget::text_input("Word Search", &self.word_search) - .on_input(Message::WordSearchInput) - .on_submit(Message::SubmitWordSearch) - .id("word-search"), + text_input( + "Search query, ie: Gen 1:1", + &self.states[col_index].bible_search + ) + .on_input(move |s| Message::BibleSearchInput(col_index, s)) + .on_submit(Message::BibleSearchSubmit(col_index)), + widget::text_input("Word Search", &self.states[col_index].word_search) + .on_input(move |s| Message::WordSearchInput(col_index, s)) + .on_submit(Message::SubmitWordSearch(col_index)), row![ - button("Clear All").on_press(Message::Clear), - button("Copy Scripture").on_press(Message::CopyText), + button("Clear All").on_press_with(move || Message::Clear(col_index)), + button("Copy Scripture") + .on_press_with(move || Message::CopyText(col_index)), ], row![ - scrollable(column( - self.word_search_results - .clone() - .unwrap_or(Vec::new()) - .into_iter() - .map(|i| button(text(i.clone())) - .on_press_with(move || Message::QuickSearch(i.to_owned())) - .into()) - )), - scrollable(text(body.clone())) + scrollable( + column( + self.states[col_index] + .word_search_results + .clone() + .unwrap_or(Vec::new()) + .into_iter() + .map(|i| button(text(i.clone())) + .on_press_with(move || Message::QuickSearch( + col_index, + i.to_owned() + )) + .into()) + ) + .padding([5, 5]) + ), + scrollable(text( + if let Some(body) = self.states[col_index].scripture_body.clone() { + parse(&body) + } else { + String::new() + } + )) ], - ], - button(text("+").center()) - .height(Length::Fixed(200.)) - .on_press(Message::AddColRight) - ] - .width(Length::Fixed(800.)) - .into() - })) - // .width(Length::Fixed(1000.)) - ) - .direction(Direction::Both { vertical: Scrollbar::new(), horizontal: Scrollbar::new() }) + ] + .padding([10, 5]) + .width(800.) + .into() + })), + button(text("+").center()) + .height(Length::Fixed(200.)) + .on_press(Message::AddColRight) + ]) + .direction(Direction::Horizontal(Scrollbar::new())) .into() } }