mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Defined Component and State
This commit is contained in:
@@ -24,4 +24,64 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
pub(crate) mod props;
|
pub mod props;
|
||||||
|
|
||||||
|
// locals
|
||||||
|
use props::{Props, PropsBuilder};
|
||||||
|
// ext
|
||||||
|
use crossterm::event::Event as InputEvent;
|
||||||
|
use tui::widgets::Widget;
|
||||||
|
|
||||||
|
// -- States
|
||||||
|
|
||||||
|
/// ## States
|
||||||
|
///
|
||||||
|
/// States is a trait which defines the behaviours for the states model for the different component.
|
||||||
|
/// A state contains internal values for each component.
|
||||||
|
pub(crate) trait States {
|
||||||
|
/// ### update
|
||||||
|
///
|
||||||
|
/// Create a new state from current one and new
|
||||||
|
fn update(&self, new: dyn States) -> dyn States;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Component
|
||||||
|
|
||||||
|
/// ## Component
|
||||||
|
///
|
||||||
|
/// Component is a trait which defines the behaviours for a Layout component.
|
||||||
|
/// All layout components must implement a method to render and one to update
|
||||||
|
pub trait Component {
|
||||||
|
/// ### render
|
||||||
|
///
|
||||||
|
/// Based on the current properties and states, return a Widget instance for the Component
|
||||||
|
/// Returns None if the component is hidden
|
||||||
|
fn render(&self) -> Option<Box<dyn Widget>>;
|
||||||
|
|
||||||
|
/// ### update
|
||||||
|
///
|
||||||
|
/// Update component properties
|
||||||
|
/// Properties should first be retrieved through `get_props` which creates a builder from
|
||||||
|
/// existing properties and then edited before calling update
|
||||||
|
fn update(&mut self, props: Option<Props>);
|
||||||
|
|
||||||
|
/// ### get_props
|
||||||
|
///
|
||||||
|
/// Returns a props builder starting from component properties.
|
||||||
|
/// This returns a prop builder in order to make easier to create
|
||||||
|
/// new properties for the element.
|
||||||
|
fn get_props(&self) -> PropsBuilder;
|
||||||
|
|
||||||
|
/// ### on
|
||||||
|
///
|
||||||
|
/// Handle input event and update internal states
|
||||||
|
fn on(&mut self, ev: InputEvent);
|
||||||
|
|
||||||
|
// -- events
|
||||||
|
|
||||||
|
/// ### should_umount
|
||||||
|
///
|
||||||
|
/// The component must provide to the supervisor whether it should be umounted (destroyed)
|
||||||
|
/// This makes sense to be called after an `on` or after an `update`, where the states changes.
|
||||||
|
fn should_umount(&self) -> bool;
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,11 +31,12 @@ use tui::style::Color;
|
|||||||
// Callback types
|
// Callback types
|
||||||
pub type OnSubmitCb = fn(&mut dyn Activity, Option<String>); // Activity, Value
|
pub type OnSubmitCb = fn(&mut dyn Activity, Option<String>); // Activity, Value
|
||||||
|
|
||||||
// --- Props
|
// -- Props
|
||||||
|
|
||||||
/// ## Props
|
/// ## Props
|
||||||
///
|
///
|
||||||
/// Props holds all the possible properties for a layout component
|
/// Props holds all the possible properties for a layout component
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Props {
|
pub struct Props {
|
||||||
// Values
|
// Values
|
||||||
pub visible: bool, // Is the element visible ON CREATE?
|
pub visible: bool, // Is the element visible ON CREATE?
|
||||||
@@ -66,7 +67,7 @@ impl Default for Props {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Props builder
|
// -- Props builder
|
||||||
|
|
||||||
/// ## PropsBuilder
|
/// ## PropsBuilder
|
||||||
///
|
///
|
||||||
@@ -76,6 +77,13 @@ pub struct PropsBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PropsBuilder {
|
impl PropsBuilder {
|
||||||
|
/// ### from_props
|
||||||
|
///
|
||||||
|
/// Create a props builder from existing properties
|
||||||
|
pub fn from_props(props: Props) -> Self {
|
||||||
|
PropsBuilder { props: Some(props) }
|
||||||
|
}
|
||||||
|
|
||||||
/// ### build
|
/// ### build
|
||||||
///
|
///
|
||||||
/// Build Props from builder
|
/// Build Props from builder
|
||||||
@@ -172,11 +180,12 @@ impl Default for PropsBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Text parts
|
// -- Text parts
|
||||||
|
|
||||||
/// ## TextParts
|
/// ## TextParts
|
||||||
///
|
///
|
||||||
/// TextParts holds optional component for the text displayed by a component
|
/// TextParts holds optional component for the text displayed by a component
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct TextParts {
|
pub struct TextParts {
|
||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
pub body: Option<Vec<String>>,
|
pub body: Option<Vec<String>>,
|
||||||
@@ -248,6 +257,47 @@ mod tests {
|
|||||||
assert_eq!(props.visible, false);
|
assert_eq!(props.visible, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_ui_layout_props_build_twice() {
|
||||||
|
let mut builder: PropsBuilder = PropsBuilder::default();
|
||||||
|
let _ = builder.build();
|
||||||
|
builder
|
||||||
|
.hidden()
|
||||||
|
.with_background(Color::Blue)
|
||||||
|
.with_foreground(Color::Green)
|
||||||
|
.bold()
|
||||||
|
.italic()
|
||||||
|
.underlined()
|
||||||
|
.on_submit(on_submit_cb)
|
||||||
|
.with_texts(TextParts::new(
|
||||||
|
Some(String::from("hello")),
|
||||||
|
Some(vec![String::from("hey")]),
|
||||||
|
));
|
||||||
|
// Rebuild
|
||||||
|
let _ = builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ui_layout_props_builder_from_props() {
|
||||||
|
let props: Props = PropsBuilder::default()
|
||||||
|
.hidden()
|
||||||
|
.with_background(Color::Blue)
|
||||||
|
.with_foreground(Color::Green)
|
||||||
|
.bold()
|
||||||
|
.italic()
|
||||||
|
.underlined()
|
||||||
|
.on_submit(on_submit_cb)
|
||||||
|
.with_texts(TextParts::new(
|
||||||
|
Some(String::from("hello")),
|
||||||
|
Some(vec![String::from("hey")]),
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
// Ok, now make a builder from properties
|
||||||
|
let builder: PropsBuilder = PropsBuilder::from_props(props);
|
||||||
|
assert!(builder.props.is_some());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ui_layout_props_text_parts_with_values() {
|
fn test_ui_layout_props_text_parts_with_values() {
|
||||||
let parts: TextParts = TextParts::new(
|
let parts: TextParts = TextParts::new(
|
||||||
|
|||||||
Reference in New Issue
Block a user