Skip to content

Commit

Permalink
modularise inidividual renderable widgets
Browse files Browse the repository at this point in the history
  • Loading branch information
Hyde46 committed May 20, 2024
1 parent 9a57099 commit 6ab086b
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 45 deletions.
9 changes: 4 additions & 5 deletions src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ mod search;
use eyre::Result;
use ratatui::{prelude::*, widgets::*};
use std::io::stdout;
use std::{
error::Error,
io,
time::{Duration, Instant},
};
use std::time::{Duration, Instant};
use termion::event::Key;
use termion::raw::IntoRawMode;
use termion::screen::IntoAlternateScreen;
Expand All @@ -35,6 +31,8 @@ pub struct App {
pub should_exit: bool,
// ratatui list of commands to display
pub commands: ListState,
// vertical scroll position of the command list
pub vertical_scroll: usize,
// ratatui list of collections to display
pub collections: ListState,
// current screen to draw
Expand All @@ -56,6 +54,7 @@ impl Default for App {
trove: Trove::default(),
search_string: String::new(),
collection: String::from(DEFAULT_COLLECTIONS[0]),
vertical_scroll: 0,
};
state.commands.select(Some(0));
state.collections.select(Some(0));
Expand Down
101 changes: 61 additions & 40 deletions src/ui/search/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,59 @@ pub fn draw_search_screen(frame: &mut Frame, app: &mut App) {
)
.split(frame.size());

render_version_header(frame, main_layout[0]);
render_version_header_widget(frame, main_layout[0]);

render_main_screen(frame, main_layout[1], app);

render_search_field(frame, main_layout[2], app);
render_search_field_widget(frame, main_layout[2], app);
}

/// Draw the main screen
///
/// # Arguments
/// * `frame` - The frame to draw the UI components
/// * `rect` - The area to draw the main screen
/// * `app` - The application state
fn render_main_screen(frame: &mut Frame, rect: Rect, app: &mut App) {
let main_screen_layout = Layout::new(
Direction::Horizontal,
[
Constraint::Percentage(30), // Scrollable tray for a list of available commands
Constraint::Percentage(70), // Detail view for the "hovered" command by the selector
],
)
.split(rect);

render_commands_list_widget(frame, main_screen_layout[0], app);

render_command_detail(frame, main_screen_layout[1], app);
}

fn render_command_detail(frame: &mut Frame, rect: Rect, app: &mut App) {
let detail_layout = Layout::new(
Direction::Vertical,
[
Constraint::Percentage(20),
Constraint::Percentage(30),
Constraint::Percentage(50),
],
)
.split(rect);

render_command_string_widget(frame, detail_layout[0], app);

render_command_description_widget(frame, detail_layout[1], app);

render_command_subdetails_widget(frame, detail_layout[2], app);
}


/// Draw the version header
///
/// # Arguments
/// * `frame` - The frame to draw the UI components
/// * `rect` - The area to draw the version header
fn render_version_header(frame: &mut Frame, rect: Rect) {
fn render_version_header_widget(frame: &mut Frame, rect: Rect) {
let version = format!("Hoard v{}", VERSION);

frame.render_widget(Paragraph::new(version), rect);
Expand All @@ -48,29 +88,14 @@ fn render_version_header(frame: &mut Frame, rect: Rect) {
/// * `frame` - The frame to draw the UI components
/// * `rect` - The area to draw the search field
/// * `app` - The application state
fn render_search_field(frame: &mut Frame, rect: Rect, app: &mut App) {
fn render_search_field_widget(frame: &mut Frame, rect: Rect, app: &mut App) {
let search_string = format!("[ {} ] > {}", app.collection, app.search_string);

frame.render_widget(Paragraph::new(search_string), rect);
}

/// Draw the main screen
///
/// # Arguments
/// * `frame` - The frame to draw the UI components
/// * `rect` - The area to draw the main screen
/// * `app` - The application state
fn render_main_screen(frame: &mut Frame, rect: Rect, app: &mut App) {
let main_screen_layout = Layout::new(
Direction::Horizontal,
[
Constraint::Percentage(30), // Scrollable tray for a list of available commands
Constraint::Percentage(70), // Detail view for the "hovered" command by the selector
],
)
.split(rect);

let vertical_scroll = 0; // from app state
fn render_commands_list_widget(frame: &mut Frame, rect: Rect, app: &mut App) {
let vertical_scroll = app.vertical_scroll; // from app state

let items = vec![
Line::from(vec![
Expand All @@ -90,7 +115,6 @@ fn render_main_screen(frame: &mut Frame, rect: Rect, app: &mut App) {
Line::from(" go_to_home"),
];

// let paragraph = Paragraph::new(Line::from(vec!["Hello, ".into(), "world!".red()]));
let paragraph = Paragraph::new(items.clone())
.scroll((vertical_scroll as u16, 0))
.block(Block::new().borders(Borders::ALL)); // to show a background for the scrollbar
Expand All @@ -101,47 +125,44 @@ fn render_main_screen(frame: &mut Frame, rect: Rect, app: &mut App) {

let mut scrollbar_state = ScrollbarState::new(items.len()).position(vertical_scroll);

let area = main_screen_layout[0];
frame.render_widget(paragraph, rect);

frame.render_widget(paragraph, area);
// and the scrollbar, those are separate widgets
frame.render_stateful_widget(
scrollbar,
area.inner(&Margin {
rect.inner(&Margin {
// using an inner vertical margin of 1 unit makes the scrollbar inside the block
vertical: 1,
horizontal: 0,
}),
&mut scrollbar_state,
);
}

let detail_layout = Layout::new(
Direction::Vertical,
[
Constraint::Percentage(20),
Constraint::Percentage(30),
Constraint::Percentage(50),
],
)
.split(main_screen_layout[1]);

fn render_command_string_widget(frame: &mut Frame, rect: Rect, app: &mut App) {
frame.render_widget(
Paragraph::new("cd /home/monarch/code")
.block(Block::default().borders(Borders::ALL).title(" Command "))
.alignment(Alignment::Center)
.wrap(Wrap { trim: false }),
detail_layout[0],
rect,
);
}

fn render_command_description_widget(frame: &mut Frame, rect: Rect, app: &mut App) {
frame.render_widget(
//Block::new().borders(Borders::RIGHT | Borders::TOP),
Paragraph::new("This is a longwinded description about the command, Probably left side aligned makes the most sense here").block(Block::default().borders(Borders::ALL).title(" Description ")).alignment(Alignment::Left).wrap(Wrap { trim: false }),
detail_layout[1]
Paragraph::new("This is a longwinded description about the command, Probably left side aligned makes the most sense here")
.block(Block::default().borders(Borders::ALL).title(" Description "))
.alignment(Alignment::Left)
.wrap(Wrap { trim: false }),
rect,
);
}

fn render_command_subdetails_widget(frame: &mut Frame, rect: Rect, app: &mut App) {
frame.render_widget(
//Block::new().borders(Borders::BOTTOM | Borders::RIGHT | Borders::TOP),
Block::new().borders(Borders::ALL),
detail_layout[2],
rect,
);
}

0 comments on commit 6ab086b

Please sign in to comment.