Compare commits

...

2 Commits

Author SHA1 Message Date
8a10b62755 Works, scroll isn't as nice as I'd like 2025-03-27 02:33:57 -06:00
82c662f00f I'm cooking 2025-03-27 01:36:03 -06:00

View File

@ -1,7 +1,11 @@
#![feature(iter_map_windows)]
use iced::{
Element, Task, clipboard,
widget::{self, button, column, combo_box, row, scrollable, text, text_input},
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::*;
@ -35,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<String>,
struct ColState {
selected_file: Option<String>,
bible_selected: Option<bible::Bible>,
@ -56,9 +59,29 @@ struct State {
word_search: 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,
}
impl Default for State {
fn default() -> Self {
let files = if let Ok(contents) = fs::read_dir(BIBLE_DIRECTORY) {
@ -85,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,
}
}
@ -102,110 +117,122 @@ impl Default for State {
impl State {
fn update(&mut self, msg: Message) -> Task<Message> {
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::<bible::Bible>(&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::<Message>(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<Message> {
let body = if let Some(body) = self.scripture_body.clone() {
parse(&body)
} else {
String::new()
};
scrollable(row((0..self.cols).map(|_| {
row![
button("-"),
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(iced::Length::FillPortion(1))
.on_press(Message::AddColRight)
]
.into()
})))
.direction(scrollable::Direction::Both {
vertical: scrollable::Scrollbar::new(),
horizontal: scrollable::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()
}
}