Skip to content

Commit

Permalink
add react block for use in react-style components
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastian Thiel committed Jun 5, 2019
1 parent b2f5187 commit b6004e2
Showing 1 changed file with 179 additions and 0 deletions.
179 changes: 179 additions & 0 deletions src/interactive/react.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,4 +200,183 @@ mod terminal {
}
}

mod block {
//! Derived from TUI-rs, license: MIT, Copyright (c) 2016 Florian Dehau
use crate::interactive::react::Component;
use std::borrow::{Borrow, BorrowMut};
use std::marker::PhantomData;
use tui::{
buffer::Buffer,
layout::Rect,
style::Color,
style::Style,
symbols::line,
widgets::{Borders, Widget},
};

pub fn fill_background(area: Rect, buf: &mut Buffer, color: Color) {
for y in area.top()..area.bottom() {
for x in area.left()..area.right() {
buf.get_mut(x, y).set_bg(color);
}
}
}

#[derive(Clone, Copy, Default)]
pub struct Block<'a, T>(PhantomData<&'a T>);

pub struct BlockProps<'a> {
/// Optional title place on the upper left of the block
title: Option<&'a str>,
/// Title style
title_style: Style,
/// Visible borders
borders: Borders,
/// Border style
border_style: Style,
/// Widget style
style: Style,
}

impl<'a> Default for BlockProps<'a> {
fn default() -> BlockProps<'a> {
BlockProps {
title: None,
title_style: Default::default(),
borders: Borders::NONE,
border_style: Default::default(),
style: Default::default(),
}
}
}

impl<'a> BlockProps<'a> {
/// Compute the inner area of a block based on its border visibility rules.
pub fn inner(&self, area: Rect) -> Rect {
if area.width < 2 || area.height < 2 {
return Rect::default();
}
let mut inner = area;
if self.borders.intersects(Borders::LEFT) {
inner.x += 1;
inner.width -= 1;
}
if self.borders.intersects(Borders::TOP) || self.title.is_some() {
inner.y += 1;
inner.height -= 1;
}
if self.borders.intersects(Borders::RIGHT) {
inner.width -= 1;
}
if self.borders.intersects(Borders::BOTTOM) {
inner.height -= 1;
}
inner
}
}

impl<'a, T> Component for Block<'a, T> {
type Props = BlockProps<'a>;
type PropsMut = ();

fn render(
&mut self,
props: impl Borrow<Self::Props>,
_: impl BorrowMut<Self::PropsMut>,
area: Rect,
buf: &mut Buffer,
) {
if area.width < 2 || area.height < 2 {
return;
}
let BlockProps {
title,
title_style,
borders,
border_style,
style,
} = props.borrow();

fill_background(area, buf, style.bg);

// Sides
if borders.intersects(Borders::LEFT) {
for y in area.top()..area.bottom() {
buf.get_mut(area.left(), y)
.set_symbol(line::VERTICAL)
.set_style(*border_style);
}
}
if borders.intersects(Borders::TOP) {
for x in area.left()..area.right() {
buf.get_mut(x, area.top())
.set_symbol(line::HORIZONTAL)
.set_style(*border_style);
}
}
if borders.intersects(Borders::RIGHT) {
let x = area.right() - 1;
for y in area.top()..area.bottom() {
buf.get_mut(x, y)
.set_symbol(line::VERTICAL)
.set_style(*border_style);
}
}
if borders.intersects(Borders::BOTTOM) {
let y = area.bottom() - 1;
for x in area.left()..area.right() {
buf.get_mut(x, y)
.set_symbol(line::HORIZONTAL)
.set_style(*border_style);
}
}

// Corners
if borders.contains(Borders::LEFT | Borders::TOP) {
buf.get_mut(area.left(), area.top())
.set_symbol(line::TOP_LEFT)
.set_style(*border_style);
}
if borders.contains(Borders::RIGHT | Borders::TOP) {
buf.get_mut(area.right() - 1, area.top())
.set_symbol(line::TOP_RIGHT)
.set_style(*border_style);
}
if borders.contains(Borders::LEFT | Borders::BOTTOM) {
buf.get_mut(area.left(), area.bottom() - 1)
.set_symbol(line::BOTTOM_LEFT)
.set_style(*border_style);
}
if borders.contains(Borders::RIGHT | Borders::BOTTOM) {
buf.get_mut(area.right() - 1, area.bottom() - 1)
.set_symbol(line::BOTTOM_RIGHT)
.set_style(*border_style);
}

if area.width > 2 {
if let Some(title) = title {
let lx = if borders.intersects(Borders::LEFT) {
1
} else {
0
};
let rx = if borders.intersects(Borders::RIGHT) {
1
} else {
0
};
let width = area.width - lx - rx;
buf.set_stringn(
area.left() + lx,
area.top(),
title,
width as usize,
*title_style,
);
}
}
}
}
}

pub use terminal::*;

0 comments on commit b6004e2

Please sign in to comment.