done for today
This commit is contained in:
+17
-2
@@ -47,8 +47,7 @@ fn run_app<B: Backend>(
|
|||||||
tick_rate: Duration,
|
tick_rate: Duration,
|
||||||
) -> Result<(), Box<dyn Error>>
|
) -> Result<(), Box<dyn Error>>
|
||||||
where
|
where
|
||||||
B::Error: 'static,
|
B::Error: 'static,{
|
||||||
{
|
|
||||||
let mut last_tick = Instant::now();
|
let mut last_tick = Instant::now();
|
||||||
loop {
|
loop {
|
||||||
terminal.draw(|frame| ui::render(frame, &mut app))?;
|
terminal.draw(|frame| ui::render(frame, &mut app))?;
|
||||||
@@ -77,4 +76,20 @@ where
|
|||||||
|
|
||||||
pub fn get_servers<'a>() -> Vec<Server<'a>> {
|
pub fn get_servers<'a>() -> Vec<Server<'a>> {
|
||||||
//todo: add printer ip addrs
|
//todo: add printer ip addrs
|
||||||
|
let printers: Vec<Server<'a>> = vec![
|
||||||
|
crate::app::Server{
|
||||||
|
name: "Micron+",
|
||||||
|
location:"Office",
|
||||||
|
ip:"192.168.1.247",
|
||||||
|
connected:false,
|
||||||
|
},
|
||||||
|
crate::app::Server{
|
||||||
|
name: "LDO V0.2",
|
||||||
|
location: "Office",
|
||||||
|
ip: "192.168.1.217",
|
||||||
|
connected: false,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return crate::app::Servers::new(printers).servers;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,199 +6,13 @@ use ratatui::{
|
|||||||
Frame,
|
Frame,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::app::{App, CurrentScreen, CurrentlyEditing};
|
use crate::app::App;
|
||||||
|
|
||||||
// ANCHOR: method_sig
|
// ANCHOR: method_sig
|
||||||
pub fn ui(frame: &mut Frame, app: &App) {
|
pub fn ui(frame: &mut Frame, app: &App) {
|
||||||
// ANCHOR_END: method_sig
|
|
||||||
// Create the layout sections.
|
|
||||||
// ANCHOR: ui_layout
|
|
||||||
let chunks = Layout::default()
|
|
||||||
.direction(Direction::Vertical)
|
|
||||||
.constraints([
|
|
||||||
Constraint::Length(3),
|
|
||||||
Constraint::Min(1),
|
|
||||||
Constraint::Length(3),
|
|
||||||
])
|
|
||||||
.split(frame.area());
|
|
||||||
// ANCHOR_END: ui_layout
|
|
||||||
|
|
||||||
// ANCHOR: title_paragraph
|
|
||||||
let title_block = Block::default()
|
|
||||||
.borders(Borders::ALL)
|
|
||||||
.style(Style::default());
|
|
||||||
|
|
||||||
let title = Paragraph::new(Text::styled(
|
|
||||||
"Create New Json",
|
|
||||||
Style::default().fg(Color::Green),
|
|
||||||
))
|
|
||||||
.block(title_block);
|
|
||||||
|
|
||||||
frame.render_widget(title, chunks[0]);
|
|
||||||
// ANCHOR_END: title_paragraph
|
|
||||||
// ANCHOR: key_value_list
|
|
||||||
let mut list_items = Vec::<ListItem>::new();
|
|
||||||
|
|
||||||
for key in app.pairs.keys() {
|
|
||||||
list_items.push(ListItem::new(Line::from(Span::styled(
|
|
||||||
format!("{: <25} : {}", key, app.pairs.get(key).unwrap()),
|
|
||||||
Style::default().fg(Color::Yellow),
|
|
||||||
))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let list = List::new(list_items);
|
pub fn render(frame: &mut Frame, app: &mut App) {
|
||||||
|
|
||||||
frame.render_widget(list, chunks[1]);
|
|
||||||
// ANCHOR_END: key_value_list
|
|
||||||
// ANCHOR: lower_navigation_current_screen
|
|
||||||
let current_navigation_text = vec![
|
|
||||||
// The first half of the text
|
|
||||||
match app.current_screen {
|
|
||||||
CurrentScreen::Main => Span::styled("Normal Mode", Style::default().fg(Color::Green)),
|
|
||||||
CurrentScreen::Editing => {
|
|
||||||
Span::styled("Editing Mode", Style::default().fg(Color::Yellow))
|
|
||||||
}
|
|
||||||
CurrentScreen::Exiting => Span::styled("Exiting", Style::default().fg(Color::LightRed)),
|
|
||||||
}
|
|
||||||
.to_owned(),
|
|
||||||
// A white divider bar to separate the two sections
|
|
||||||
Span::styled(" | ", Style::default().fg(Color::White)),
|
|
||||||
// The final section of the text, with hints on what the user is editing
|
|
||||||
{
|
|
||||||
if let Some(editing) = &app.currently_editing {
|
|
||||||
match editing {
|
|
||||||
CurrentlyEditing::Key => {
|
|
||||||
Span::styled("Editing Json Key", Style::default().fg(Color::Green))
|
|
||||||
}
|
|
||||||
CurrentlyEditing::Value => {
|
|
||||||
Span::styled("Editing Json Value", Style::default().fg(Color::LightGreen))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Span::styled("Not Editing Anything", Style::default().fg(Color::DarkGray))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
let mode_footer = Paragraph::new(Line::from(current_navigation_text))
|
|
||||||
.block(Block::default().borders(Borders::ALL));
|
|
||||||
// ANCHOR_END: lower_navigation_current_screen
|
|
||||||
|
|
||||||
// ANCHOR: lower_navigation_key_hint
|
|
||||||
let current_keys_hint = {
|
|
||||||
match app.current_screen {
|
|
||||||
CurrentScreen::Main => Span::styled(
|
|
||||||
"(q) to quit / (e) to make new pair",
|
|
||||||
Style::default().fg(Color::Red),
|
|
||||||
),
|
|
||||||
CurrentScreen::Editing => Span::styled(
|
|
||||||
"(ESC) to cancel/(Tab) to switch boxes/enter to complete",
|
|
||||||
Style::default().fg(Color::Red),
|
|
||||||
),
|
|
||||||
CurrentScreen::Exiting => Span::styled(
|
|
||||||
"(q) to quit / (e) to make new pair",
|
|
||||||
Style::default().fg(Color::Red),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let key_notes_footer =
|
|
||||||
Paragraph::new(Line::from(current_keys_hint)).block(Block::default().borders(Borders::ALL));
|
|
||||||
// ANCHOR_END: lower_navigation_key_hint
|
|
||||||
|
|
||||||
// ANCHOR: lower_navigation_layout
|
|
||||||
let footer_chunks = Layout::default()
|
|
||||||
.direction(Direction::Horizontal)
|
|
||||||
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
|
|
||||||
.split(chunks[2]);
|
|
||||||
// ANCHOR_END: lower_navigation_layout
|
|
||||||
|
|
||||||
// ANCHOR: lower_navigation_rendering
|
|
||||||
frame.render_widget(mode_footer, footer_chunks[0]);
|
|
||||||
frame.render_widget(key_notes_footer, footer_chunks[1]);
|
|
||||||
// ANCHOR_END: lower_navigation_rendering
|
|
||||||
|
|
||||||
// ANCHOR: editing_popup
|
|
||||||
if let Some(editing) = &app.currently_editing {
|
|
||||||
let popup_block = Block::default()
|
|
||||||
.title("Enter a new key-value pair")
|
|
||||||
.borders(Borders::NONE)
|
|
||||||
.style(Style::default().bg(Color::DarkGray));
|
|
||||||
|
|
||||||
let area = centered_rect(60, 25, frame.area());
|
|
||||||
frame.render_widget(popup_block, area);
|
|
||||||
// ANCHOR_END: editing_popup
|
|
||||||
|
|
||||||
// ANCHOR: popup_layout
|
|
||||||
let popup_chunks = Layout::default()
|
|
||||||
.direction(Direction::Horizontal)
|
|
||||||
.margin(1)
|
|
||||||
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
|
|
||||||
.split(area);
|
|
||||||
// ANCHOR_END: popup_layout
|
|
||||||
|
|
||||||
// ANCHOR: key_value_blocks
|
|
||||||
let mut key_block = Block::default().title("Key").borders(Borders::ALL);
|
|
||||||
let mut value_block = Block::default().title("Value").borders(Borders::ALL);
|
|
||||||
|
|
||||||
let active_style = Style::default().bg(Color::LightYellow).fg(Color::Black);
|
|
||||||
|
|
||||||
match editing {
|
|
||||||
CurrentlyEditing::Key => key_block = key_block.style(active_style),
|
|
||||||
CurrentlyEditing::Value => value_block = value_block.style(active_style),
|
|
||||||
};
|
|
||||||
|
|
||||||
let key_text = Paragraph::new(app.key_input.clone()).block(key_block);
|
|
||||||
frame.render_widget(key_text, popup_chunks[0]);
|
|
||||||
|
|
||||||
let value_text = Paragraph::new(app.value_input.clone()).block(value_block);
|
|
||||||
frame.render_widget(value_text, popup_chunks[1]);
|
|
||||||
}
|
|
||||||
// ANCHOR_END: key_value_blocks
|
|
||||||
|
|
||||||
// ANCHOR: exit_screen
|
|
||||||
if let CurrentScreen::Exiting = app.current_screen {
|
|
||||||
frame.render_widget(Clear, frame.area()); //this clears the entire screen and anything already drawn
|
|
||||||
let popup_block = Block::default()
|
|
||||||
.title("Y/N")
|
|
||||||
.borders(Borders::NONE)
|
|
||||||
.style(Style::default().bg(Color::DarkGray));
|
|
||||||
|
|
||||||
let exit_text = Text::styled(
|
|
||||||
"Would you like to output the buffer as json? (y/n)",
|
|
||||||
Style::default().fg(Color::Red),
|
|
||||||
);
|
|
||||||
// the `trim: false` will stop the text from being cut off when over the edge of the block
|
|
||||||
let exit_paragraph = Paragraph::new(exit_text)
|
|
||||||
.block(popup_block)
|
|
||||||
.wrap(Wrap { trim: false });
|
|
||||||
|
|
||||||
let area = centered_rect(60, 25, frame.area());
|
|
||||||
frame.render_widget(exit_paragraph, area);
|
|
||||||
}
|
|
||||||
// ANCHOR_END: exit_screen
|
|
||||||
}
|
|
||||||
|
|
||||||
// ANCHOR: centered_rect
|
|
||||||
/// helper function to create a centered rect using up certain percentage of the available rect `r`
|
|
||||||
fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
|
|
||||||
// Cut the given rectangle into three vertical pieces
|
|
||||||
let popup_layout = Layout::default()
|
|
||||||
.direction(Direction::Vertical)
|
|
||||||
.constraints([
|
|
||||||
Constraint::Percentage((100 - percent_y) / 2),
|
|
||||||
Constraint::Percentage(percent_y),
|
|
||||||
Constraint::Percentage((100 - percent_y) / 2),
|
|
||||||
])
|
|
||||||
.split(r);
|
|
||||||
|
|
||||||
// Then cut the middle vertical piece into three width-wise pieces
|
|
||||||
Layout::default()
|
|
||||||
.direction(Direction::Horizontal)
|
|
||||||
.constraints([
|
|
||||||
Constraint::Percentage((100 - percent_x) / 2),
|
|
||||||
Constraint::Percentage(percent_x),
|
|
||||||
Constraint::Percentage((100 - percent_x) / 2),
|
|
||||||
])
|
|
||||||
.split(popup_layout[1])[1] // Return the middle chunk
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user