working on tab... checkpoint
This commit is contained in:
parent
789c593f7e
commit
727b2f0b51
167
src/main.rs
167
src/main.rs
@ -1,4 +1,7 @@
|
|||||||
#![feature(iter_map_windows)]
|
#![feature(iter_map_windows)]
|
||||||
|
use iced::keyboard::key::Named;
|
||||||
|
use iced::keyboard::{Key, Modifiers};
|
||||||
|
use iced::{event, task, Event, Subscription};
|
||||||
use iced::widget::scrollable;
|
use iced::widget::scrollable;
|
||||||
use iced::{
|
use iced::{
|
||||||
Element, Length, Task, Theme, clipboard, color,
|
Element, Length, Task, Theme, clipboard, color,
|
||||||
@ -43,32 +46,14 @@ fn main() -> iced::Result {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ALL BUILTIN THEMES
|
// THEMES
|
||||||
// Light
|
// Dark - KanagawaDragon
|
||||||
// Dark
|
// Default - Nord
|
||||||
// Dracula
|
// Light - TokyoNightLight
|
||||||
// Nord
|
|
||||||
// SolarizedLight
|
|
||||||
// SolarizedDark
|
|
||||||
// GruvboxLight
|
|
||||||
// GruvboxDark
|
|
||||||
// CatppuccinLatte
|
|
||||||
// CatppuccinFrappe
|
|
||||||
// CatppuccinMacchiato
|
|
||||||
// CatppuccinMocha
|
|
||||||
// TokyoNight
|
|
||||||
// TokyoNightStorm
|
|
||||||
// TokyoNightLight
|
|
||||||
// KanagawaWave
|
|
||||||
// KanagawaDragon
|
|
||||||
// KanagawaLotus
|
|
||||||
// Moonfly
|
|
||||||
// Nightfly
|
|
||||||
// Oxocarbon
|
|
||||||
// Ferra
|
|
||||||
|
|
||||||
// GUI
|
// GUI
|
||||||
iced::application("Bible Study", State::update, State::view)
|
iced::application("Bible Study", State::update, State::view)
|
||||||
|
.subscription(State::subscription)
|
||||||
.theme(|_| Theme::Nord)
|
.theme(|_| Theme::Nord)
|
||||||
.run()
|
.run()
|
||||||
}
|
}
|
||||||
@ -85,6 +70,10 @@ enum Message {
|
|||||||
QuickSearch(usize, String, usize),
|
QuickSearch(usize, String, usize),
|
||||||
AddColRight,
|
AddColRight,
|
||||||
DeleteColumn(usize),
|
DeleteColumn(usize),
|
||||||
|
ErrorSelectingBible(usize),
|
||||||
|
RecievedEvent(Event),
|
||||||
|
ColSelected(usize),
|
||||||
|
ColUnselected,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ColState {
|
struct ColState {
|
||||||
@ -96,6 +85,8 @@ struct ColState {
|
|||||||
|
|
||||||
word_search: String,
|
word_search: String,
|
||||||
word_search_results: Option<Vec<(String, bool)>>,
|
word_search_results: Option<Vec<(String, bool)>>,
|
||||||
|
|
||||||
|
error: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ColState {
|
impl Default for ColState {
|
||||||
@ -109,6 +100,41 @@ impl Default for ColState {
|
|||||||
|
|
||||||
word_search: String::new(),
|
word_search: String::new(),
|
||||||
word_search_results: None,
|
word_search_results: None,
|
||||||
|
|
||||||
|
error: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
enum SelectedInputBox {
|
||||||
|
Bible,
|
||||||
|
VerseSearch,
|
||||||
|
WordSearch,
|
||||||
|
}
|
||||||
|
impl SelectedInputBox {
|
||||||
|
fn in_order() -> Vec<Self> {
|
||||||
|
vec![
|
||||||
|
SelectedInputBox::Bible,
|
||||||
|
SelectedInputBox::VerseSearch,
|
||||||
|
SelectedInputBox::WordSearch
|
||||||
|
]
|
||||||
|
}
|
||||||
|
fn next(current: &Option<Self>) -> Self {
|
||||||
|
if let Some(input) = current {
|
||||||
|
if let Some(found) = Self::in_order().into_iter().find(|a| a==input) {
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// I don't see why this would panic
|
||||||
|
Self::in_order().into_iter().next().unwrap()
|
||||||
|
}
|
||||||
|
fn as_id_prefix(&self) -> &str {
|
||||||
|
// magic values that relate to id() as setup in the GUI
|
||||||
|
match self {
|
||||||
|
SelectedInputBox::Bible => "",
|
||||||
|
SelectedInputBox::VerseSearch => "verse-",
|
||||||
|
SelectedInputBox::WordSearch => "word-",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,6 +143,9 @@ struct State {
|
|||||||
files: combo_box::State<String>,
|
files: combo_box::State<String>,
|
||||||
states: Vec<ColState>,
|
states: Vec<ColState>,
|
||||||
cols: usize,
|
cols: usize,
|
||||||
|
/// Incase an event needs a best guess column
|
||||||
|
last_selected_column: Option<usize>,
|
||||||
|
last_selected_input: Option<SelectedInputBox>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for State {
|
impl Default for State {
|
||||||
@ -147,13 +176,74 @@ impl Default for State {
|
|||||||
files: combo_box::State::new(files),
|
files: combo_box::State::new(files),
|
||||||
states: vec![ColState::default()],
|
states: vec![ColState::default()],
|
||||||
cols: 1,
|
cols: 1,
|
||||||
|
last_selected_column: None,
|
||||||
|
last_selected_input: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
|
|
||||||
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
|
event::listen().map(Message::RecievedEvent)
|
||||||
|
}
|
||||||
|
|
||||||
fn update(&mut self, msg: Message) -> Task<Message> {
|
fn update(&mut self, msg: Message) -> Task<Message> {
|
||||||
|
// handle tab ordering
|
||||||
match msg {
|
match msg {
|
||||||
|
Message::WordSearchInput(_, _) => self.last_selected_input = Some(SelectedInputBox::WordSearch),
|
||||||
|
Message::BibleSearchInput(_, _) => self.last_selected_input = Some(SelectedInputBox::VerseSearch),
|
||||||
|
Message::DeleteColumn(_) => self.last_selected_input = None,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to set last_selected_column for messages with side effects
|
||||||
|
match msg {
|
||||||
|
// All events that give column index
|
||||||
|
Message::ErrorSelectingBible(i) |
|
||||||
|
Message::BibleSelected(i, _) |
|
||||||
|
Message::QuickSearch(i, _, _) |
|
||||||
|
Message::BibleSearchInput(i,_) |
|
||||||
|
Message::WordSearchInput(i, _) |
|
||||||
|
Message::BibleSearchSubmit(i) |
|
||||||
|
Message::SubmitWordSearch(i) |
|
||||||
|
Message::CopyText(i) |
|
||||||
|
Message::Clear(i)
|
||||||
|
=> self.last_selected_column = Some(i),
|
||||||
|
Message::DeleteColumn(_) => self.last_selected_column = None,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// match normal messages
|
||||||
|
match msg {
|
||||||
|
Message::ColSelected(i) => self.last_selected_column = Some(i),
|
||||||
|
Message::ColUnselected => self.last_selected_column = None,
|
||||||
|
Message::RecievedEvent(event) => {
|
||||||
|
if let Event::Keyboard(kbd) =event {
|
||||||
|
if let iced::keyboard::Event::KeyReleased {key, modifiers, ..} = kbd {
|
||||||
|
if let Key::Named(n) = key {
|
||||||
|
if let Named::Tab = n {
|
||||||
|
if let Some(i) = self.last_selected_column {
|
||||||
|
if modifiers == Modifiers::SHIFT {
|
||||||
|
// Shirft + Tab
|
||||||
|
let next = SelectedInputBox::next(&self.last_selected_input);
|
||||||
|
let id = next.as_id_prefix();
|
||||||
|
return text_input::focus(format!("{id}{}", i));
|
||||||
|
} else {
|
||||||
|
// Tab
|
||||||
|
|
||||||
|
// TODO prev
|
||||||
|
return text_input::focus(format!("verse-{}", i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Message::ErrorSelectingBible(i) => {
|
||||||
|
self.states[i].error = Some(String::new());
|
||||||
|
}
|
||||||
Message::DeleteColumn(idx) => {
|
Message::DeleteColumn(idx) => {
|
||||||
self.cols -= 1;
|
self.cols -= 1;
|
||||||
self.states.remove(idx);
|
self.states.remove(idx);
|
||||||
@ -165,8 +255,10 @@ impl State {
|
|||||||
self.states.push(ColState::default())
|
self.states.push(ColState::default())
|
||||||
}
|
}
|
||||||
Message::BibleSelected(i, file) => {
|
Message::BibleSelected(i, file) => {
|
||||||
if let Ok(contents) = fs::read_to_string(&file) {
|
match fs::read_to_string(&file) {
|
||||||
if let Ok(bible) = quick_xml::de::from_str::<bible::Bible>(&contents) {
|
Ok(contents) => {
|
||||||
|
match quick_xml::de::from_str::<bible::Bible>(&contents) {
|
||||||
|
Ok(bible) => {
|
||||||
// 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.states[i].selected_file = Some(format!("{bible}"));
|
self.states[i].selected_file = Some(format!("{bible}"));
|
||||||
@ -174,6 +266,16 @@ impl State {
|
|||||||
// 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");
|
||||||
}
|
}
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("{}", err);
|
||||||
|
return self.update(Message::ErrorSelectingBible(i));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("{}", err);
|
||||||
|
return self.update(Message::ErrorSelectingBible(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::QuickSearch(i, s, result_index) => {
|
Message::QuickSearch(i, s, result_index) => {
|
||||||
@ -184,8 +286,12 @@ impl State {
|
|||||||
}
|
}
|
||||||
return self.update(Message::BibleSearchSubmit(i));
|
return self.update(Message::BibleSearchSubmit(i));
|
||||||
}
|
}
|
||||||
Message::BibleSearchInput(i, query) => self.states[i].bible_search = query,
|
Message::BibleSearchInput(i, query) => {
|
||||||
Message::WordSearchInput(i, query) => self.states[i].word_search = query,
|
self.states[i].bible_search = query
|
||||||
|
},
|
||||||
|
Message::WordSearchInput(i, query) => {
|
||||||
|
self.states[i].word_search = query
|
||||||
|
},
|
||||||
Message::BibleSearchSubmit(i) => {
|
Message::BibleSearchSubmit(i) => {
|
||||||
let mut splits = self.states[i].bible_search.split_whitespace();
|
let mut splits = self.states[i].bible_search.split_whitespace();
|
||||||
let book = splits.next();
|
let book = splits.next();
|
||||||
@ -218,13 +324,13 @@ impl State {
|
|||||||
self.states[i].word_search_results = None;
|
self.states[i].word_search_results = None;
|
||||||
self.states[i].bible_search = String::new();
|
self.states[i].bible_search = String::new();
|
||||||
self.states[i].word_search = String::new();
|
self.states[i].word_search = String::new();
|
||||||
// return text_input::focus("bible-search");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<Message> {
|
fn view(&self) -> Element<Message> {
|
||||||
|
//TODO error message
|
||||||
scrollable(
|
scrollable(
|
||||||
row![
|
row![
|
||||||
row((0..self.cols).map(|col_index| {
|
row((0..self.cols).map(|col_index| {
|
||||||
@ -239,14 +345,17 @@ impl State {
|
|||||||
"Select Bible",
|
"Select Bible",
|
||||||
self.states[col_index].selected_file.as_ref(),
|
self.states[col_index].selected_file.as_ref(),
|
||||||
move |s| Message::BibleSelected(col_index, s)
|
move |s| Message::BibleSelected(col_index, s)
|
||||||
),
|
)
|
||||||
|
.on_open(Message::ColSelected(col_index)),
|
||||||
text_input(
|
text_input(
|
||||||
"Search query, ie: Gen 1:1",
|
"Search query, ie: Gen 1:1",
|
||||||
&self.states[col_index].bible_search
|
&self.states[col_index].bible_search
|
||||||
)
|
)
|
||||||
|
.id(format!("verse-{}", col_index))
|
||||||
.on_input(move |s| Message::BibleSearchInput(col_index, s))
|
.on_input(move |s| Message::BibleSearchInput(col_index, s))
|
||||||
.on_submit(Message::BibleSearchSubmit(col_index)),
|
.on_submit(Message::BibleSearchSubmit(col_index)),
|
||||||
widget::text_input("Word Search", &self.states[col_index].word_search)
|
widget::text_input("Word Search", &self.states[col_index].word_search)
|
||||||
|
.id(format!("word-{}", col_index))
|
||||||
.on_input(move |s| Message::WordSearchInput(col_index, s))
|
.on_input(move |s| Message::WordSearchInput(col_index, s))
|
||||||
.on_submit(Message::SubmitWordSearch(col_index)),
|
.on_submit(Message::SubmitWordSearch(col_index)),
|
||||||
row![
|
row![
|
||||||
|
Loading…
x
Reference in New Issue
Block a user