aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/frontend/app.rs7
-rw-r--r--src/frontend/keywords.rs40
-rw-r--r--src/frontend/ui.rs91
3 files changed, 116 insertions, 22 deletions
diff --git a/src/frontend/app.rs b/src/frontend/app.rs
index 8eb2e65..8d6454d 100644
--- a/src/frontend/app.rs
+++ b/src/frontend/app.rs
@@ -77,7 +77,7 @@ impl App {
let main_bibfile = args.bibfilearg;
let main_biblio = BibiMain::new(main_bibfile.clone());
let biblio_data = BibiData::new(&main_biblio.bibliography, &main_biblio.citekeys);
- let tag_list = TagList::from_iter(main_biblio.keyword_list.clone());
+ let tag_list = TagList::new(main_biblio.keyword_list.clone());
let search_struct = BibiSearch::default();
let entry_table = EntryTable::from_iter(biblio_data.entry_list.bibentries.clone());
let current_area = CurrentArea::EntryArea;
@@ -131,7 +131,8 @@ impl App {
self.main_biblio = BibiMain::new(self.main_bibfile.clone());
self.biblio_data =
BibiData::new(&self.main_biblio.bibliography, &self.main_biblio.citekeys);
- self.tag_list = TagList::from_iter(self.main_biblio.keyword_list.clone());
+ // self.tag_list = TagList::from_iter(self.main_biblio.keyword_list.clone());
+ self.tag_list = TagList::new(self.main_biblio.keyword_list.clone());
self.entry_table = EntryTable::from_iter(self.biblio_data.entry_list.bibentries.clone());
}
@@ -157,7 +158,7 @@ impl App {
pub fn reset_current_list(&mut self) {
self.entry_table = EntryTable::from_iter(self.biblio_data.entry_list.bibentries.clone());
- self.tag_list = TagList::from_iter(self.main_biblio.keyword_list.clone());
+ self.tag_list = TagList::new(self.main_biblio.keyword_list.clone());
if let CurrentArea::TagArea = self.current_area {
self.tag_list.tag_list_state.select(Some(0))
}
diff --git a/src/frontend/keywords.rs b/src/frontend/keywords.rs
index 0363609..9432752 100644
--- a/src/frontend/keywords.rs
+++ b/src/frontend/keywords.rs
@@ -21,9 +21,10 @@ use ratatui::widgets::{ListState, ScrollbarState};
#[derive(Debug)]
pub struct TagList {
- pub tag_list_items: Vec<TagListItem>,
+ pub tag_list_items: Vec<String>,
pub tag_list_state: ListState,
pub tag_scroll_state: ScrollbarState,
+ pub selected_keyword: String,
}
// Structure of the list items.
@@ -41,18 +42,33 @@ impl TagListItem {
}
}
-impl FromIterator<String> for TagList {
- fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> Self {
- let tag_list_items: Vec<TagListItem> = iter
- .into_iter()
- .map(|info| TagListItem::new(&info))
- .collect();
+// impl FromIterator<String> for TagList {
+// fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> Self {
+// let tag_list_items: Vec<TagListItem> = iter
+// .into_iter()
+// .map(|info| TagListItem::new(&info))
+// .collect();
+// let tag_list_state = ListState::default(); // for preselection: .with_selected(Some(0));
+// let tag_scroll_state = ScrollbarState::new(tag_list_items.len());
+// Self {
+// tag_list_items,
+// tag_list_state,
+// tag_scroll_state,
+// selected_keyword: String::new(),
+// }
+// }
+// }
+
+impl TagList {
+ pub fn new(keyword_list: Vec<String>) -> Self {
+ let tag_list_items = keyword_list;
let tag_list_state = ListState::default(); // for preselection: .with_selected(Some(0));
let tag_scroll_state = ScrollbarState::new(tag_list_items.len());
Self {
tag_list_items,
tag_list_state,
tag_scroll_state,
+ selected_keyword: String::new(),
}
}
}
@@ -92,7 +108,8 @@ impl App {
pub fn get_selected_tag(&self) -> &str {
let idx = self.tag_list.tag_list_state.selected().unwrap();
- let keyword = &self.tag_list.tag_list_items[idx].keyword;
+ let keyword = &self.tag_list.tag_list_items[idx];
+ // let keyword = &self.tag_list.tag_list_items[idx].keyword;
keyword
}
@@ -100,7 +117,8 @@ impl App {
let orig_list = &self.main_biblio.keyword_list;
let filtered_list =
BibiSearch::search_tag_list(&self.search_struct.search_string, orig_list.clone());
- self.tag_list = TagList::from_iter(filtered_list)
+ self.tag_list.tag_list_items = filtered_list;
+ // self.tag_list = TagList::from_iter(filtered_list)
}
pub fn filter_tags_by_entries(&mut self) {
@@ -124,7 +142,7 @@ impl App {
filtered_keywords.dedup();
self.search_struct.filtered_tag_list = filtered_keywords.clone();
- self.tag_list = TagList::from_iter(filtered_keywords);
+ self.tag_list.tag_list_items = filtered_keywords;
}
// Filter the entry list by tags when hitting enter
@@ -134,9 +152,11 @@ impl App {
let orig_list = &self.entry_table.entry_table_items;
let keyword = self.get_selected_tag();
let filtered_list = BibiSearch::filter_entries_by_tag(&keyword, &orig_list);
+ self.tag_list.selected_keyword = keyword.to_string();
self.entry_table.entry_table_items = filtered_list;
self.filter_tags_by_entries();
self.toggle_area();
+ self.entry_table.entry_table_state.select(Some(0));
self.former_area = Some(FormerArea::TagArea);
}
}
diff --git a/src/frontend/ui.rs b/src/frontend/ui.rs
index a328df7..7ad17c9 100644
--- a/src/frontend/ui.rs
+++ b/src/frontend/ui.rs
@@ -23,7 +23,7 @@ use ratatui::{
text::{Line, Span, Text},
widgets::{
block::{Position, Title},
- Block, Cell, HighlightSpacing, List, ListItem, Padding, Paragraph, Row, Scrollbar,
+ Block, Borders, Cell, HighlightSpacing, List, ListItem, Padding, Paragraph, Row, Scrollbar,
ScrollbarOrientation, StatefulWidget, Table, Widget, Wrap,
},
};
@@ -78,6 +78,9 @@ impl Widget for &mut App {
let [list_area, item_area] =
Layout::vertical([Constraint::Fill(1), Constraint::Fill(1)]).areas(main_area);
+ let [entry_area, entry_info_area] =
+ Layout::vertical([Constraint::Fill(1), Constraint::Length(2)]).areas(list_area);
+
let [tag_area, info_area] =
Layout::horizontal([Constraint::Max(25), Constraint::Min(35)]).areas(item_area);
@@ -85,7 +88,8 @@ impl Widget for &mut App {
App::render_header(header_area, buf);
self.render_footer(footer_area, buf);
// Render list area where entry gets selected
- self.render_entrytable(list_area, buf);
+ self.render_entrytable(entry_area, buf);
+ self.render_file_info(entry_info_area, buf);
// Render infos related to selected entry
self.render_taglist(tag_area, buf);
self.render_selected_item(info_area, buf);
@@ -156,8 +160,78 @@ impl App {
}
}
+ // Render info of the current file and process
+ // 1. Basename of the currently loaded file
+ // 2. Keyword by which the entries are filtered at the moment
+ // 3. Currently selected entry and total count of entries
+ pub fn render_file_info(&mut self, area: Rect, buf: &mut Buffer) {
+ let block = Block::new() // can also be Block::new
+ // Leave Top empty to simulate one large box with borders of entry list
+ .borders(Borders::LEFT | Borders::RIGHT | Borders::BOTTOM)
+ .border_set(if let CurrentArea::EntryArea = self.current_area {
+ symbols::border::THICK
+ } else {
+ symbols::border::PLAIN
+ })
+ .border_style(if let CurrentArea::EntryArea = self.current_area {
+ BOX_SELECTED_BOX_STYLE
+ } else {
+ BOX_UNSELECTED_BORDER_STYLE
+ });
+
+ let background_style = Color::Indexed(235);
+
+ let [file_area, keyword_area, count_area] = Layout::horizontal([
+ Constraint::Fill(4),
+ Constraint::Fill(2),
+ Constraint::Fill(1),
+ ])
+ .horizontal_margin(1)
+ .areas(area);
+
+ Line::from(vec![
+ Span::raw("File: ").bold(),
+ Span::raw(self.main_bibfile.file_name().unwrap().to_string_lossy()).bold(),
+ ])
+ .bg(background_style)
+ .render(file_area, buf);
+
+ Line::from(if !self.tag_list.selected_keyword.is_empty() {
+ vec![
+ Span::raw("Filtered by: "),
+ Span::raw(self.tag_list.selected_keyword.to_string())
+ .bold()
+ .green(),
+ ]
+ } else {
+ vec![Span::raw(" ")]
+ })
+ .bg(background_style)
+ .render(keyword_area, buf);
+
+ Line::from(if self.entry_table.entry_table_state.selected().is_some() {
+ vec![
+ Span::raw((self.entry_table.entry_table_state.selected().unwrap() + 1).to_string())
+ .bold(),
+ Span::raw("/"),
+ Span::raw(self.entry_table.entry_table_items.len().to_string()),
+ ]
+ } else {
+ vec![Span::raw("No entries")]
+ })
+ .right_aligned()
+ .bg(background_style)
+ .render(count_area, buf);
+ // Paragraph::new(Line::from(vec![Span::raw(
+ // self.main_bibfile.display().to_string(),
+ // )]))
+ // .block(block)
+ // .render(area, buf);
+ Widget::render(block, area, buf)
+ }
+
pub fn render_entrytable(&mut self, area: Rect, buf: &mut Buffer) {
- let block = Block::bordered() // can also be Block::new
+ let block = Block::new() // can also be Block::new
.title(
Line::styled(
" Bibliographic Entries ",
@@ -169,6 +243,7 @@ impl App {
)
.centered(),
)
+ .borders(Borders::LEFT | Borders::RIGHT | Borders::TOP)
.border_set(if let CurrentArea::EntryArea = self.current_area {
symbols::border::THICK
} else {
@@ -179,11 +254,8 @@ impl App {
} else {
BOX_UNSELECTED_BORDER_STYLE
});
- // .bg(Color::Black); // .bg(NORMAL_ROW_BG);
+
let header_style = Style::default().bold().fg(TEXT_FG_COLOR);
- // let selected_style = Style::default()
- // .add_modifier(Modifier::REVERSED)
- // .add_modifier(Modifier::BOLD);
let header = [
"Authors".underlined(),
@@ -196,6 +268,7 @@ impl App {
.collect::<Row>()
.style(header_style)
.height(1);
+
// Iterate over vector storing each entries data fields
let rows = self
.entry_table
@@ -237,7 +310,7 @@ impl App {
.orientation(ScrollbarOrientation::VerticalRight)
.track_symbol(None)
.begin_symbol(SCROLLBAR_UPPER_CORNER)
- .end_symbol(SCROLLBAR_LOWER_CORNER)
+ .end_symbol(None)
.thumb_style(Style::new().fg(Color::DarkGray));
if let CurrentArea::EntryArea = self.current_area {
@@ -405,7 +478,7 @@ impl App {
.enumerate()
.map(|(_i, todo_item)| {
// let color = alternate_colors(i);
- ListItem::from(todo_item) //.bg(color)
+ ListItem::from(todo_item.to_owned()) //.bg(color)
})
.collect();