use crate::_private::NonExhaustive;
use ratatui::buffer::Buffer;
use ratatui::layout::Rect;
use ratatui::style::Style;
use ratatui::widgets::StatefulWidget;
#[cfg(feature = "unstable-widget-ref")]
use ratatui::widgets::StatefulWidgetRef;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum ShadowDirection {
#[default]
BottomRight,
BottomLeft,
TopRight,
TopLeft,
}
#[derive(Debug, Default, Clone)]
pub struct Shadow {
style: Style,
dir: ShadowDirection,
}
impl Shadow {
pub fn new() -> Self {
Self::default()
}
pub fn styles(mut self, styles: ShadowStyle) -> Self {
self.style = styles.style;
self.dir = styles.dir;
self
}
pub fn style(mut self, style: Style) -> Self {
self.style = style;
self
}
pub fn direction(mut self, direction: ShadowDirection) -> Self {
self.dir = direction;
self
}
}
#[derive(Debug)]
pub struct ShadowStyle {
pub style: Style,
pub dir: ShadowDirection,
pub non_exhaustive: NonExhaustive,
}
impl Default for ShadowStyle {
fn default() -> Self {
Self {
style: Default::default(),
dir: Default::default(),
non_exhaustive: NonExhaustive,
}
}
}
#[cfg(feature = "unstable-widget-ref")]
impl StatefulWidgetRef for Shadow {
type State = ();
fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
render_ref(&self, area, buf, state);
}
}
impl StatefulWidget for Shadow {
type State = ();
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
render_ref(&self, area, buf, state);
}
}
fn render_ref(widget: &Shadow, area: Rect, buf: &mut Buffer, _state: &mut ()) {
match widget.dir {
ShadowDirection::BottomRight => {
for y in area.top() + 1..area.bottom() + 1 {
if let Some(cell) = buf.cell_mut((area.right(), y)) {
cell.set_style(widget.style);
}
}
for x in area.left() + 1..area.right() {
if let Some(cell) = buf.cell_mut((x, area.bottom())) {
cell.set_style(widget.style);
}
}
}
ShadowDirection::BottomLeft => {
if area.left() > 0 {
for y in area.top() + 1..area.bottom() + 1 {
if let Some(cell) = buf.cell_mut((area.left() - 1, y)) {
cell.set_style(widget.style);
}
}
}
for x in area.left()..area.right().saturating_sub(1) {
if let Some(cell) = buf.cell_mut((x, area.bottom())) {
cell.set_style(widget.style);
}
}
}
ShadowDirection::TopRight => {
for y in area.top().saturating_sub(1)..area.bottom().saturating_sub(1) {
if let Some(cell) = buf.cell_mut((area.right(), y)) {
cell.set_style(widget.style);
}
}
if area.top() > 0 {
for x in area.left() + 1..area.right() {
if let Some(cell) = buf.cell_mut((x, area.top() - 1)) {
cell.set_style(widget.style);
}
}
}
}
ShadowDirection::TopLeft => {
if area.left() > 0 {
for y in area.top().saturating_sub(1)..area.bottom().saturating_sub(1) {
if let Some(cell) = buf.cell_mut((area.left() - 1, y)) {
cell.set_style(widget.style);
}
}
}
if area.top() > 0 {
for x in area.left()..area.right().saturating_sub(1) {
if let Some(cell) = buf.cell_mut((x, area.top() - 1)) {
cell.set_style(widget.style);
}
}
}
}
}
}