made TAB a switcher for widgets

This commit is contained in:
Thomas Eppers 2021-08-28 17:37:55 +02:00
parent 0031c46d4b
commit 7748212878
4 changed files with 100 additions and 50 deletions

View File

@ -11,7 +11,7 @@ use tui::Terminal;
use crate::tags; use crate::tags;
use crate::widget::repo_entry; use crate::widget::repo_entry;
use crate::widget::tag_list; use crate::widget::tag_list;
use crate::widget::Widget; // use crate::widget::Widget;
pub struct Ui { pub struct Ui {
state: State, state: State,
@ -51,14 +51,20 @@ impl Ui {
.constraints([Constraint::Length(3), Constraint::Min(1)].as_ref()) .constraints([Constraint::Length(3), Constraint::Min(1)].as_ref())
.split(rect.size()); .split(rect.size());
rect.render_widget(ui.repo.render(), chunks[0]); rect.render_widget(ui.repo.render(&ui.state), chunks[0]);
let (list, state) = ui.tags.render(); let (list, state) = ui.tags.render(&ui.state);
rect.render_stateful_widget(list, chunks[1], state); rect.render_stateful_widget(list, chunks[1], state);
}) })
.unwrap(); .unwrap();
//handle input //handle input
match receiver.try_recv() { match receiver.try_recv() {
Ok(Key::Char('\t')) => {
ui.state = match ui.state {
State::EditRepo => State::SelectTag,
State::SelectTag => State::EditRepo,
};
}
Ok(Key::Ctrl('q')) => break 'core, //quit program without saving Ok(Key::Ctrl('q')) => break 'core, //quit program without saving
Ok(Key::Ctrl('s')) => { Ok(Key::Ctrl('s')) => {
if ui.state == State::SelectTag { if ui.state == State::SelectTag {
@ -67,34 +73,34 @@ impl Ui {
} }
Ok(Key::Char('\n')) => { Ok(Key::Char('\n')) => {
if ui.state == State::EditRepo { if ui.state == State::EditRepo {
ui.state = State::SelectTag;
ui.repo.confirm(); ui.repo.confirm();
//TODO query tags and show them switch
match tags::Tags::get_tags(ui.repo.get()) { match tags::Tags::get_tags(ui.repo.get()) {
Ok(lines) => ui.tags = tag_list::TagList::new(lines), Ok(lines) => ui.tags = tag_list::TagList::new(lines),
Err(_) => (), Err(_) => {
ui.tags = tag_list::TagList::new_line(
"Error fetich tags. Is there a typo in the Repository?",
);
} }
} }
} }
Ok(Key::Down) => {
if ui.state == State::SelectTag {
ui.tags.next();
} }
Ok(Key::Char(key)) => {
if ui.state == State::EditRepo {
ui.tags = tag_list::TagList::new_line("Editing Repository");
} }
Ok(Key::Up) => { ui.repo.handle_input(&ui.state, Key::Char(key));
if ui.state == State::SelectTag { ui.tags.handle_input(&ui.state, Key::Char(key));
ui.tags.previous();
}
} }
Ok(Key::Backspace) => { Ok(Key::Backspace) => {
ui.state = State::EditRepo; if ui.state == State::EditRepo {
ui.repo.input(Key::Backspace); ui.tags = tag_list::TagList::new_line("Editing Repository");
ui.tags = tag_list::TagList::new(vec![String::from("editing Repository")]); }
ui.repo.handle_input(&ui.state, Key::Backspace);
ui.tags.handle_input(&ui.state, Key::Backspace);
} }
Ok(key) => { Ok(key) => {
ui.state = State::EditRepo; ui.repo.handle_input(&ui.state, key);
ui.repo.input(key); ui.tags.handle_input(&ui.state, key);
ui.tags = tag_list::TagList::new(vec![String::from("editing Repository")]);
} }
_ => (), _ => (),
} }

View File

@ -1,8 +1,2 @@
use tui::widgets::ListState;
pub mod repo_entry; pub mod repo_entry;
pub mod tag_list; pub mod tag_list;
pub trait Widget {
fn input(&mut self, event: termion::event::Key);
}

View File

@ -3,6 +3,8 @@ use tui::layout::Alignment;
use tui::style::{Color, Style}; use tui::style::{Color, Style};
use tui::widgets::{Block, Borders, Paragraph}; use tui::widgets::{Block, Borders, Paragraph};
use crate::ui::State;
pub struct RepoEntry { pub struct RepoEntry {
text: String, text: String,
old_text: String, old_text: String,
@ -22,39 +24,54 @@ impl RepoEntry {
self.text.clone() self.text.clone()
} }
pub fn render(&self) -> Paragraph { pub fn render(&self, state: &crate::ui::State) -> Paragraph {
let title = match self.changed { let title = match self.changed {
true => "Repository*", true => "Repository*",
false => "Repository", false => "Repository",
}; };
let border_style = if state == &crate::ui::State::EditRepo {
Style::default().fg(Color::Green)
} else {
Style::default().fg(Color::Gray)
};
Paragraph::new(self.text.clone()) Paragraph::new(self.text.clone())
.block(Block::default().title(title).borders(Borders::ALL)) .block(
Block::default()
.title(title)
.borders(Borders::ALL)
.border_style(border_style),
)
.style(Style::default().fg(Color::White).bg(Color::Black)) .style(Style::default().fg(Color::White).bg(Color::Black))
.alignment(Alignment::Left) .alignment(Alignment::Left)
} }
pub fn handle_input(&mut self, state: &State, key: termion::event::Key) {
if state != &State::EditRepo {
return;
}
match key {
// Key::Char('\n') => self.confirm(), //handled in Ui
Key::Char(c) => {
self.text.push(c);
self.changed = true;
}
Key::Backspace => {
self.text.pop();
self.changed = true;
}
Key::Esc => {
self.text = self.old_text.clone();
self.changed = false;
}
_ => (),
}
}
pub fn confirm(&mut self) { pub fn confirm(&mut self) {
self.old_text = self.text.clone(); self.old_text = self.text.clone();
self.changed = false; self.changed = false;
} }
} }
impl super::Widget for RepoEntry {
fn input(&mut self, key: termion::event::Key) {
match key {
Key::Esc => {
self.text = self.old_text.clone(); //TODO return to other structure
self.changed = false;
}
Key::Backspace => {
self.text.pop();
self.changed = true;
}
Key::Char(c) => {
self.text.push(c);
self.changed = true;
}
_ => (),
}
}
}

View File

@ -1,6 +1,9 @@
use termion::event::Key;
use tui::style::{Color, Style}; use tui::style::{Color, Style};
use tui::widgets::{Block, Borders, List, ListState}; use tui::widgets::{Block, Borders, List, ListState};
use crate::ui::State;
pub struct TagList { pub struct TagList {
list: Vec<String>, list: Vec<String>,
state: ListState, state: ListState,
@ -14,7 +17,20 @@ impl TagList {
} }
} }
pub fn render(&mut self) -> (List, &mut ListState) { pub fn new_line(line: &str) -> Self {
Self {
list: vec![String::from(line)],
state: ListState::default(),
}
}
pub fn render(&mut self, state: &State) -> (List, &mut ListState) {
let border_style = if state == &State::SelectTag {
Style::default().fg(Color::Green)
} else {
Style::default().fg(Color::Gray)
};
let items: Vec<tui::widgets::ListItem> = self let items: Vec<tui::widgets::ListItem> = self
.list .list
.iter() .iter()
@ -26,7 +42,12 @@ impl TagList {
// Create a List from all list items and highlight the currently selected one // Create a List from all list items and highlight the currently selected one
let items = List::new(items) let items = List::new(items)
.block(Block::default().title("Tags").borders(Borders::ALL)) .block(
Block::default()
.title("Tags")
.borders(Borders::ALL)
.border_style(border_style),
)
.style(Style::default().fg(Color::White).bg(Color::Black)) .style(Style::default().fg(Color::White).bg(Color::Black))
.highlight_style(Style::default().bg(Color::Black)) .highlight_style(Style::default().bg(Color::Black))
.highlight_symbol(">>"); .highlight_symbol(">>");
@ -34,6 +55,18 @@ impl TagList {
(items, &mut self.state) (items, &mut self.state)
} }
pub fn handle_input(&mut self, state: &State, key: termion::event::Key) {
if state != &State::SelectTag {
return;
}
match key {
Key::Down => self.next(),
Key::Up => self.previous(),
_ => (),
}
}
pub fn next(&mut self) { pub fn next(&mut self) {
match self.state.selected() { match self.state.selected() {
None if self.list.len() > 0 => self.state.select(Some(0)), None if self.list.len() > 0 => self.state.select(Some(0)),