Component Active State

This commit is contained in:
2024-10-23 23:10:28 +08:00
parent 579ffead41
commit 9c93085afe
7 changed files with 92 additions and 20 deletions

View File

@@ -22,3 +22,18 @@ fn center_rect(area: Rect, width: u16, height: u16) -> Rect {
let [area] = horizontal.areas(area); let [area] = horizontal.areas(area);
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
}
}

View File

@@ -3,12 +3,16 @@ use std::io;
use crossterm::event::Event; use crossterm::event::Event;
use ratatui::widgets::Widget; use ratatui::widgets::Widget;
use super::ActiveState;
pub mod block; pub mod block;
pub mod help; pub mod help;
pub mod input; pub mod input;
pub mod list; pub mod list;
pub trait Component { pub trait Component {
type EventResult;
fn widget(&self) -> impl Widget; fn widget(&self) -> impl Widget;
fn event_handler(&mut self, event: &Event) -> io::Result<()>; fn event_handler(&mut self, event: &Event) -> io::Result<Self::EventResult>;
fn active_state(&mut self) -> &mut ActiveState;
} }

View File

@@ -1,17 +1,19 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use ratatui::widgets::{Block, Borders}; use ratatui::{style::{Style, Stylize}, widgets::{Block, Borders}};
#[derive(Default)] #[derive(Default)]
pub struct BlockComponent<'a> { pub struct BlockComponent<'a> {
_phantom: PhantomData<&'a ()>, _phantom: PhantomData<&'a ()>,
title: String, title: String,
active: bool,
} }
impl<'a> BlockComponent<'a> { impl<'a> BlockComponent<'a> {
pub fn widget(&self) -> Block<'a> { pub fn widget(&self) -> Block<'a> {
Block::default() Block::default()
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(if self.active {Style::new().blue()} else {Style::new().white()})
.title(self.title.clone()) .title(self.title.clone())
} }
@@ -19,4 +21,9 @@ impl<'a> BlockComponent<'a> {
self.title = text; self.title = text;
self self
} }
pub fn active(mut self, active: bool) -> Self {
self.active = active;
self
}
} }

View File

@@ -3,12 +3,17 @@ use std::io;
use crossterm::event::Event; use crossterm::event::Event;
use ratatui::widgets::{Paragraph, Widget}; use ratatui::widgets::{Paragraph, Widget};
use crate::view::ActiveState;
use super::{block::BlockComponent, Component}; use super::{block::BlockComponent, Component};
#[derive(Default)] #[derive(Default)]
pub struct HelpComponent {} pub struct HelpComponent {
active_state: ActiveState
}
impl Component for HelpComponent { impl Component for HelpComponent {
type EventResult = ();
fn widget(&self) -> impl Widget { fn widget(&self) -> impl Widget {
let block = BlockComponent::default().title("Help".to_string()).widget(); let block = BlockComponent::default().title("Help".to_string()).widget();
let help = Paragraph::new("Temp").block(block); let help = Paragraph::new("Temp").block(block);
@@ -17,4 +22,7 @@ impl Component for HelpComponent {
fn event_handler(&mut self, _event: &Event) -> io::Result<()> { fn event_handler(&mut self, _event: &Event) -> io::Result<()> {
Ok(()) Ok(())
} }
fn active_state(&mut self) -> &mut ActiveState {
&mut self.active_state
}
} }

View File

@@ -1,6 +1,5 @@
use std::io; use std::io;
use super::{block::BlockComponent, Component};
use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers}; use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
use ratatui::{ use ratatui::{
layout::{Position, Rect}, layout::{Position, Rect},
@@ -8,6 +7,10 @@ use ratatui::{
Frame, Frame,
}; };
use crate::view::ActiveState;
use super::{block::BlockComponent, Component};
pub enum InputEvent { pub enum InputEvent {
Compelete, Compelete,
None, None,
@@ -18,6 +21,7 @@ pub struct InputComponent {
name: String, name: String,
value: String, value: String,
cursor: usize, cursor: usize,
active_state: ActiveState
} }
impl InputComponent { impl InputComponent {
@@ -32,13 +36,18 @@ impl InputComponent {
} }
} }
impl Component for InputComponent { impl Component for InputComponent {
type EventResult = InputEvent;
fn widget(&self) -> impl Widget { 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); let input = Paragraph::new(self.value.clone()).block(block);
input input
} }
fn event_handler(&mut self, event: &Event) -> io::Result<InputEvent> { fn event_handler(&mut self, event: &Event) -> io::Result<InputEvent> {
if !self.active_state.is_active() {
return Ok(InputEvent::None);
}
match event { match event {
Event::Key(KeyEvent { Event::Key(KeyEvent {
kind: KeyEventKind::Press, 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
} }
} }

View File

@@ -1,4 +1,3 @@
use super::{block::BlockComponent, Component};
use crossterm::{ use crossterm::{
event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers}, event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers},
style::Color, style::Color,
@@ -8,12 +7,22 @@ use ratatui::{
widgets::{List, ListItem, Widget}, widgets::{List, ListItem, Widget},
}; };
use crate::view::ActiveState;
use super::{block::BlockComponent, Component};
pub enum ListEvent {
Select(usize),
None,
}
// #[derive(Default)] // #[derive(Default)]
pub struct ListComponent { pub struct ListComponent {
name: String, name: String,
item_keys: Vec<String>, item_keys: Vec<String>,
cursor: usize, cursor: usize,
selectable: bool, selectable: bool,
active_state: ActiveState,
} }
impl ListComponent { impl ListComponent {
@@ -37,13 +46,15 @@ impl Default for ListComponent {
item_keys: vec!["1".to_string(), "2".to_string(), "3".to_string()], item_keys: vec!["1".to_string(), "2".to_string(), "3".to_string()],
cursor: 0, cursor: 0,
selectable: false, selectable: false,
active_state: Default::default()
} }
} }
} }
impl Component for ListComponent { impl Component for ListComponent {
type EventResult = ListEvent;
fn widget(&self) -> impl Widget { 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<ListItem> = self let list_items: Vec<ListItem> = self
.item_keys .item_keys
.iter() .iter()
@@ -60,9 +71,9 @@ impl Component for ListComponent {
list list
} }
fn event_handler(&mut self, event: &Event) -> std::io::Result<()> { fn event_handler(&mut self, event: &Event) -> std::io::Result<ListEvent> {
if !self.selectable { if !self.active_state.is_active() {
return Ok(()); return Ok(ListEvent::None);
} }
match event { match event {
Event::Key(KeyEvent { Event::Key(KeyEvent {
@@ -87,11 +98,18 @@ impl Component for ListComponent {
self.cursor + 1 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
} }
} }

View File

@@ -11,8 +11,8 @@ use ratatui::{
use super::{ use super::{
component::{ component::{
help::HelpComponent, help::HelpComponent,
input::{self, InputComponent}, input::{self, InputComponent, InputEvent},
list::ListComponent, list::{ListComponent, ListEvent},
Component, Component,
}, },
setting::SettingView, setting::SettingView,
@@ -25,20 +25,20 @@ pub struct Home {
table: ListComponent, table: ListComponent,
help: HelpComponent, help: HelpComponent,
setting: SettingView, setting: SettingView,
event_recive: [bool;4],
} }
impl Default for Home { impl Default for Home {
fn default() -> Self { fn default() -> Self {
Home { let mut home = Home {
input: InputComponent::default().name("Name".to_string()), input: InputComponent::default().name("Name".to_string()),
table: ListComponent::default() table: ListComponent::default()
.selectable() .selectable()
.name("Connections".to_string()), .name("Connections".to_string()),
help: HelpComponent::default(), help: HelpComponent::default(),
setting: SettingView::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<()> { fn handle_event(&mut self, event: &Event) -> io::Result<()> {
if self.event_recive[0] {self.input.event_handler(event)?}; match self.input.event_handler(event) {
if self.event_recive[1] {self.table.event_handler(event)?}; Ok(InputEvent::None) => {}
_ => {}
}
match self.table.event_handler(event) {
Ok(ListEvent::Select(i)) => {
println!("{}", i);
}
_ => {}
}
Ok(()) Ok(())
} }
} }