Works, scroll isn't as nice as I'd like

This commit is contained in:
rushmore75 2025-03-27 02:33:57 -06:00
parent 82c662f00f
commit 8a10b62755

View File

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