diff --git a/src/view.rs b/src/view.rs index a2fb615..9bdfa35 100644 --- a/src/view.rs +++ b/src/view.rs @@ -22,3 +22,18 @@ fn center_rect(area: Rect, width: u16, height: u16) -> Rect { let [area] = horizontal.areas(area); area } + +#[derive(Default)] +pub struct ActiveState { + active_state: bool, +} + +impl ActiveState { + pub fn is_active(&self) -> bool { + self.active_state + } + + pub fn set_active(&mut self, active_state: bool) { + self.active_state = active_state + } +} diff --git a/src/view/component.rs b/src/view/component.rs index e169aa8..99931e9 100644 --- a/src/view/component.rs +++ b/src/view/component.rs @@ -3,12 +3,16 @@ use std::io; use crossterm::event::Event; use ratatui::widgets::Widget; +use super::ActiveState; + pub mod block; pub mod help; pub mod input; pub mod list; pub trait Component { + type EventResult; fn widget(&self) -> impl Widget; - fn event_handler(&mut self, event: &Event) -> io::Result<()>; + fn event_handler(&mut self, event: &Event) -> io::Result; + fn active_state(&mut self) -> &mut ActiveState; } diff --git a/src/view/component/block.rs b/src/view/component/block.rs index dfe6923..d7bdb0c 100644 --- a/src/view/component/block.rs +++ b/src/view/component/block.rs @@ -1,17 +1,19 @@ use std::marker::PhantomData; -use ratatui::widgets::{Block, Borders}; +use ratatui::{style::{Style, Stylize}, widgets::{Block, Borders}}; #[derive(Default)] pub struct BlockComponent<'a> { _phantom: PhantomData<&'a ()>, title: String, + active: bool, } impl<'a> BlockComponent<'a> { pub fn widget(&self) -> Block<'a> { Block::default() .borders(Borders::ALL) + .border_style(if self.active {Style::new().blue()} else {Style::new().white()}) .title(self.title.clone()) } @@ -19,4 +21,9 @@ impl<'a> BlockComponent<'a> { self.title = text; self } + + pub fn active(mut self, active: bool) -> Self { + self.active = active; + self + } } diff --git a/src/view/component/help.rs b/src/view/component/help.rs index 78e354c..e4e1cea 100644 --- a/src/view/component/help.rs +++ b/src/view/component/help.rs @@ -3,12 +3,17 @@ use std::io; use crossterm::event::Event; use ratatui::widgets::{Paragraph, Widget}; +use crate::view::ActiveState; + use super::{block::BlockComponent, Component}; #[derive(Default)] -pub struct HelpComponent {} +pub struct HelpComponent { + active_state: ActiveState +} impl Component for HelpComponent { + type EventResult = (); fn widget(&self) -> impl Widget { let block = BlockComponent::default().title("Help".to_string()).widget(); let help = Paragraph::new("Temp").block(block); @@ -17,4 +22,7 @@ impl Component for HelpComponent { fn event_handler(&mut self, _event: &Event) -> io::Result<()> { Ok(()) } + fn active_state(&mut self) -> &mut ActiveState { + &mut self.active_state + } } diff --git a/src/view/component/input.rs b/src/view/component/input.rs index 9d96d0d..3d09e40 100644 --- a/src/view/component/input.rs +++ b/src/view/component/input.rs @@ -1,6 +1,5 @@ use std::io; -use super::{block::BlockComponent, Component}; use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers}; use ratatui::{ layout::{Position, Rect}, @@ -8,6 +7,10 @@ use ratatui::{ Frame, }; +use crate::view::ActiveState; + +use super::{block::BlockComponent, Component}; + pub enum InputEvent { Compelete, None, @@ -18,6 +21,7 @@ pub struct InputComponent { name: String, value: String, cursor: usize, + active_state: ActiveState } impl InputComponent { @@ -32,13 +36,18 @@ impl InputComponent { } } impl Component for InputComponent { + type EventResult = InputEvent; + fn widget(&self) -> impl Widget { - let block = BlockComponent::default().title(self.name.clone()).widget(); + let block = BlockComponent::default().title(self.name.clone()).active(self.active_state.is_active()).widget(); let input = Paragraph::new(self.value.clone()).block(block); input } fn event_handler(&mut self, event: &Event) -> io::Result { + if !self.active_state.is_active() { + return Ok(InputEvent::None); + } match event { Event::Key(KeyEvent { kind: KeyEventKind::Press, @@ -73,6 +82,9 @@ impl Component for InputComponent { } _ => {} } - Ok(()) + Ok(InputEvent::None) + } + fn active_state(&mut self) -> &mut ActiveState { + &mut self.active_state } } diff --git a/src/view/component/list.rs b/src/view/component/list.rs index 7e53d39..b971aa2 100644 --- a/src/view/component/list.rs +++ b/src/view/component/list.rs @@ -1,4 +1,3 @@ -use super::{block::BlockComponent, Component}; use crossterm::{ event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers}, style::Color, @@ -8,12 +7,22 @@ use ratatui::{ widgets::{List, ListItem, Widget}, }; +use crate::view::ActiveState; + +use super::{block::BlockComponent, Component}; + +pub enum ListEvent { + Select(usize), + None, +} + // #[derive(Default)] pub struct ListComponent { name: String, item_keys: Vec, cursor: usize, selectable: bool, + active_state: ActiveState, } impl ListComponent { @@ -37,13 +46,15 @@ impl Default for ListComponent { item_keys: vec!["1".to_string(), "2".to_string(), "3".to_string()], cursor: 0, selectable: false, + active_state: Default::default() } } } impl Component for ListComponent { + type EventResult = ListEvent; fn widget(&self) -> impl Widget { - let block = BlockComponent::default().title(self.name.clone()).widget(); + let block = BlockComponent::default().title(self.name.clone()).active(self.active_state.is_active()).widget(); let list_items: Vec = self .item_keys .iter() @@ -60,9 +71,9 @@ impl Component for ListComponent { list } - fn event_handler(&mut self, event: &Event) -> std::io::Result<()> { - if !self.selectable { - return Ok(()); + fn event_handler(&mut self, event: &Event) -> std::io::Result { + if !self.active_state.is_active() { + return Ok(ListEvent::None); } match event { Event::Key(KeyEvent { @@ -87,11 +98,18 @@ impl Component for ListComponent { self.cursor + 1 } } + Enter => { + self.active_state.set_active(!self.active_state.is_active()); + return Ok(ListEvent::Select(self.cursor)) + }, _ => {} } } _ => {} } - Ok(()) + Ok(ListEvent::None) + } + fn active_state(&mut self) -> &mut ActiveState { + &mut self.active_state } } diff --git a/src/view/home.rs b/src/view/home.rs index 63b060d..b7451fc 100644 --- a/src/view/home.rs +++ b/src/view/home.rs @@ -11,8 +11,8 @@ use ratatui::{ use super::{ component::{ help::HelpComponent, - input::{self, InputComponent}, - list::ListComponent, + input::{self, InputComponent, InputEvent}, + list::{ListComponent, ListEvent}, Component, }, setting::SettingView, @@ -25,20 +25,20 @@ pub struct Home { table: ListComponent, help: HelpComponent, setting: SettingView, - event_recive: [bool;4], } impl Default for Home { fn default() -> Self { - Home { + let mut home = Home { input: InputComponent::default().name("Name".to_string()), table: ListComponent::default() .selectable() .name("Connections".to_string()), help: HelpComponent::default(), setting: SettingView::default(), - event_recive: [true, false, false, false] - } + }; + home.table.active_state().set_active(true); + home } } @@ -60,8 +60,16 @@ impl View for Home { } fn handle_event(&mut self, event: &Event) -> io::Result<()> { - if self.event_recive[0] {self.input.event_handler(event)?}; - if self.event_recive[1] {self.table.event_handler(event)?}; + match self.input.event_handler(event) { + Ok(InputEvent::None) => {} + _ => {} + } + match self.table.event_handler(event) { + Ok(ListEvent::Select(i)) => { + println!("{}", i); + } + _ => {} + } Ok(()) } }