Component Active State
This commit is contained in:
15
src/view.rs
15
src/view.rs
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user