//! This module contains a [`Shadow`] option for a [`Table`]. //! //! # Example //! //! ``` //! use tabled::{Table, settings::{Shadow, Style}}; //! //! let data = vec!["Hello", "World", "!"]; //! //! let table = Table::new(data) //! .with(Style::markdown()) //! .with(Shadow::new(1)) //! .to_string(); //! //! assert_eq!( //! table, //! concat!( //! "| &str | \n", //! "|-------|▒\n", //! "| Hello |▒\n", //! "| World |▒\n", //! "| ! |▒\n", //! " ▒▒▒▒▒▒▒▒▒", //! ) //! ); //! ``` //! //! [`Table`]: crate::Table use crate::{ grid::color::AnsiColor, grid::config::{ColoredConfig, Indent, Offset, Sides}, settings::{color::Color, TableOption}, }; /// The structure represents a shadow of a table. /// /// NOTICE: It uses [`Margin`] therefore it often can't be combined. /// /// [`Margin`]: crate::settings::Margin #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Shadow { c: char, size: usize, size_offset: usize, direction: Sides, color: Option, } impl Shadow { /// A default fill character to be used. pub const DEFAULT_FILL: char = '▒'; /// Construct's an [`Shadow`] object with default fill [`Shadow::DEFAULT_FILL`]. /// /// It uses space(' ') as a default fill character. /// To set a custom character you can use [`Self::set_fill`] function. pub fn new(size: usize) -> Self { Self { c: Self::DEFAULT_FILL, size, size_offset: 1, direction: Sides::new(false, true, false, true), color: None, } } /// The function, sets a characters for the [`Shadow`] to be used. pub fn set_fill(mut self, c: char) -> Self { self.c = c; self } /// Set an offset value (default is '1'). pub fn set_offset(mut self, size: usize) -> Self { self.size_offset = size; self } /// Switch shadow to top. pub fn set_top(mut self) -> Self { self.direction.top = true; self.direction.bottom = false; self } /// Switch shadow to bottom. pub fn set_bottom(mut self) -> Self { self.direction.bottom = true; self.direction.top = false; self } /// Switch shadow to left. pub fn set_left(mut self) -> Self { self.direction.left = true; self.direction.right = false; self } /// Switch shadow to right. pub fn set_right(mut self) -> Self { self.direction.right = true; self.direction.left = false; self } /// Sets a color for a shadow. pub fn set_color(mut self, color: Color) -> Self { self.color = Some(color); self } } impl TableOption for Shadow { fn change(self, _: &mut R, cfg: &mut ColoredConfig, _: &mut D) { set_margin(cfg, self.size, self.c, &self.direction); set_margin_offset(cfg, self.size_offset, &self.direction); if let Some(color) = &self.color { set_margin_color(cfg, color.clone().into(), &self.direction); } } } fn set_margin(cfg: &mut ColoredConfig, size: usize, c: char, direction: &Sides) { let mut margin: Sides = Sides::default(); if direction.top { margin.top.size = size; margin.top.fill = c; } if direction.bottom { margin.bottom.size = size; margin.bottom.fill = c; } if direction.left { margin.left.size = size; margin.left.fill = c; } if direction.right { margin.right.size = size; margin.right.fill = c; } cfg.set_margin(margin); } fn set_margin_offset(cfg: &mut ColoredConfig, size: usize, direction: &Sides) { let mut margin = Sides::filled(Offset::Begin(0)); if direction.right && direction.bottom { margin.bottom = Offset::Begin(size); margin.right = Offset::Begin(size); } if direction.right && direction.top { margin.top = Offset::Begin(size); margin.right = Offset::End(size); } if direction.left && direction.bottom { margin.bottom = Offset::End(size); margin.left = Offset::Begin(size); } if direction.left && direction.top { margin.top = Offset::End(size); margin.left = Offset::End(size); } cfg.set_margin_offset(margin); } fn set_margin_color(cfg: &mut ColoredConfig, color: AnsiColor<'static>, direction: &Sides) { let mut margin: Sides>> = Sides::default(); if direction.right { margin.right = Some(color.clone()); } if direction.top { margin.top = Some(color.clone()); } if direction.left { margin.left = Some(color.clone()); } if direction.bottom { margin.bottom = Some(color.clone()); } cfg.set_margin_color(margin); }