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);
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 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<Self::EventResult>;
fn active_state(&mut self) -> &mut ActiveState;
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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<InputEvent> {
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
}
}

View File

@@ -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<String>,
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<ListItem> = 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<ListEvent> {
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
}
}

View File

@@ -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(())
}
}