[tui] Implement View MenuBar actions.
You can show / hide the Logger and the Explorer now.
This commit is contained in:
parent
fa36a633ee
commit
76fe09f39b
111
src/tui/app.rs
111
src/tui/app.rs
@ -1,5 +1,5 @@
|
||||
use crate::tui::app::AppComponent::{AppEditor, AppExplorer, AppLogger};
|
||||
use crate::tui::component::{Action, Component, Focus, FocusState};
|
||||
use crate::tui::component::{Action, Component, Focus, FocusState, Visible, VisibleState};
|
||||
use crate::tui::editor_tab::EditorTab;
|
||||
use crate::tui::explorer::Explorer;
|
||||
use crate::tui::logger::Logger;
|
||||
@ -186,40 +186,87 @@ impl<'a> Widget for &mut App<'a> {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let vertical_constraints = match self.logger.component_state.vis {
|
||||
Visible::Visible => {
|
||||
vec![
|
||||
Constraint::Length(3), // top status bar
|
||||
Constraint::Percentage(70), // horizontal layout
|
||||
Constraint::Fill(1), // terminal
|
||||
Constraint::Length(3), // bottom status bar
|
||||
]
|
||||
}
|
||||
Visible::Hidden => {
|
||||
vec![
|
||||
Constraint::Length(3), // top status bar
|
||||
Constraint::Fill(1), // horizontal layout
|
||||
Constraint::Length(3), // bottom status bar
|
||||
]
|
||||
}
|
||||
};
|
||||
let vertical = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([
|
||||
Constraint::Length(3), // top status bar
|
||||
Constraint::Percentage(70), // horizontal layout
|
||||
Constraint::Percentage(30), // terminal
|
||||
Constraint::Length(3), // bottom status bar
|
||||
])
|
||||
.constraints(vertical_constraints)
|
||||
.split(area);
|
||||
|
||||
let horizontal_constraints = match self.explorer.component_state.vis {
|
||||
Visible::Visible => {
|
||||
vec![
|
||||
Constraint::Max(30), // File explorer with a max width of 30 characters.
|
||||
Constraint::Fill(1), // Editor fills the remaining space.
|
||||
]
|
||||
}
|
||||
Visible::Hidden => {
|
||||
vec![
|
||||
Constraint::Fill(1), // Editor fills the remaining space.
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
// The index used for vertical here does not care if the Logger is Visible or not.
|
||||
let horizontal = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([
|
||||
Constraint::Max(30), // File explorer with a max width of 30 characters.
|
||||
Constraint::Fill(1), // Editor fills the remaining space.
|
||||
])
|
||||
.constraints(horizontal_constraints)
|
||||
.split(vertical[1]);
|
||||
match self.explorer.component_state.vis {
|
||||
Visible::Visible => {
|
||||
let editor_layout = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([
|
||||
Constraint::Length(1), // Editor tabs.
|
||||
Constraint::Fill(1), // Editor contents.
|
||||
])
|
||||
.split(horizontal[1]);
|
||||
self.editor_tabs
|
||||
.render(editor_layout[0], editor_layout[1], buf);
|
||||
self.explorer.render(horizontal[0], buf);
|
||||
}
|
||||
Visible::Hidden => {
|
||||
let editor_layout = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([
|
||||
Constraint::Length(1), // Editor tabs.
|
||||
Constraint::Fill(1), // Editor contents.
|
||||
])
|
||||
.split(horizontal[0]);
|
||||
self.editor_tabs
|
||||
.render(editor_layout[0], editor_layout[1], buf);
|
||||
}
|
||||
}
|
||||
|
||||
let editor_layout = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([
|
||||
Constraint::Length(1), // Editor tabs.
|
||||
Constraint::Fill(1), // Editor contents.
|
||||
])
|
||||
.split(horizontal[1]);
|
||||
|
||||
self.draw_bottom_status(vertical[3], buf);
|
||||
self.editor_tabs
|
||||
.render(editor_layout[0], editor_layout[1], buf);
|
||||
self.explorer.render(horizontal[0], buf);
|
||||
self.logger.render(vertical[2], buf);
|
||||
|
||||
// The title bar is rendered last to overlay any popups created for drop-down menus.
|
||||
self.menu_bar.render(vertical[0], buf);
|
||||
match self.logger.component_state.vis {
|
||||
// Index 1 of vertical is rendered with the horizontal layout above.
|
||||
Visible::Visible => {
|
||||
self.logger.render(vertical[2], buf);
|
||||
self.draw_bottom_status(vertical[3], buf);
|
||||
// The title bar is rendered last to overlay any popups created for drop-down menus.
|
||||
self.menu_bar.render(vertical[0], buf);
|
||||
}
|
||||
Visible::Hidden => {
|
||||
self.draw_bottom_status(vertical[2], buf);
|
||||
// The title bar is rendered last to overlay any popups created for drop-down menus.
|
||||
self.menu_bar.render(vertical[0], buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,6 +302,7 @@ impl<'a> Component for App<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle actions returned from widgets that may need context on other widgets or app state.
|
||||
match action {
|
||||
Action::Quit | Action::Handled => Ok(action),
|
||||
Action::Save => match self.editor_tabs.current_editor_mut() {
|
||||
@ -270,7 +318,6 @@ impl<'a> Component for App<'a> {
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
Action::OpenTab => {
|
||||
if let Ok(path) = self.explorer.selected() {
|
||||
let path_buf = PathBuf::from(path);
|
||||
@ -296,6 +343,14 @@ impl<'a> Component for App<'a> {
|
||||
Ok(Action::Noop)
|
||||
}
|
||||
}
|
||||
Action::ShowHideLogger => {
|
||||
self.logger.component_state.togget_visible();
|
||||
Ok(Action::Handled)
|
||||
}
|
||||
Action::ShowHideExplorer => {
|
||||
self.explorer.component_state.togget_visible();
|
||||
Ok(Action::Handled)
|
||||
}
|
||||
_ => Ok(Action::Noop),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#![allow(dead_code, unused_variables)]
|
||||
|
||||
use crate::tui::component::Focus::Inactive;
|
||||
use Focus::Active;
|
||||
use anyhow::Result;
|
||||
use log::trace;
|
||||
use ratatui::crossterm::event::{Event, KeyEvent, MouseEvent};
|
||||
@ -58,6 +60,7 @@ pub trait Component {
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ComponentState {
|
||||
pub(crate) focus: Focus,
|
||||
pub(crate) vis: Visible,
|
||||
pub(crate) help_text: String,
|
||||
}
|
||||
|
||||
@ -69,7 +72,8 @@ impl ComponentState {
|
||||
fn new() -> Self {
|
||||
trace!(target:Self::id(), "Building {}", Self::id());
|
||||
Self {
|
||||
focus: Focus::Active,
|
||||
focus: Active,
|
||||
vis: Visible::Visible,
|
||||
help_text: String::new(),
|
||||
}
|
||||
}
|
||||
@ -90,8 +94,8 @@ pub enum Focus {
|
||||
impl Focus {
|
||||
pub(crate) fn get_active_color(&self) -> Color {
|
||||
match self {
|
||||
Focus::Active => Color::LightYellow,
|
||||
Focus::Inactive => Color::White,
|
||||
Active => Color::LightYellow,
|
||||
Inactive => Color::White,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -107,6 +111,7 @@ impl FocusState for ComponentState {
|
||||
fn with_focus(self, focus: Focus) -> Self {
|
||||
Self {
|
||||
focus,
|
||||
vis: Visible::Visible,
|
||||
help_text: self.help_text,
|
||||
}
|
||||
}
|
||||
@ -117,8 +122,8 @@ impl FocusState for ComponentState {
|
||||
|
||||
fn toggle_focus(&mut self) {
|
||||
match self.focus {
|
||||
Focus::Active => self.set_focus(Focus::Inactive),
|
||||
Focus::Inactive => self.set_focus(Focus::Active),
|
||||
Active => self.set_focus(Inactive),
|
||||
Inactive => self.set_focus(Active),
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,3 +131,37 @@ impl FocusState for ComponentState {
|
||||
self.focus.get_active_color()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Visible {
|
||||
#[default]
|
||||
Visible,
|
||||
Hidden,
|
||||
}
|
||||
|
||||
pub trait VisibleState {
|
||||
fn with_visible(self, vis: Visible) -> Self;
|
||||
fn set_visible(&mut self, vis: Visible);
|
||||
fn togget_visible(&mut self);
|
||||
}
|
||||
|
||||
impl VisibleState for ComponentState {
|
||||
fn with_visible(self, vis: Visible) -> Self {
|
||||
Self {
|
||||
focus: self.focus,
|
||||
vis,
|
||||
help_text: self.help_text,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_visible(&mut self, vis: Visible) {
|
||||
self.vis = vis;
|
||||
}
|
||||
|
||||
fn togget_visible(&mut self) {
|
||||
match self.vis {
|
||||
Visible::Visible => self.set_visible(Visible::Hidden),
|
||||
Visible::Hidden => self.set_visible(Visible::Visible),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user