blob: 96a3a717f57b9ac04a8e56a9d5a8aaeff372dfa8 [file] [log] [blame]
//! This example demonstrates using the [`Padding::colorize()`] function in several ways
//! to give a [`Table`] display a vibrant asthetic.
//!
//! * 🚩 This example requires the `color` feature.
//!
//! * Note how the [`Color`] [setting](tabled::settings) is used to simplify creating
//! reusable themes for text, backgrounds, padded whitespace, and borders.
//!
//! * Note how a unique color can be set for each direction.
use std::convert::TryFrom;
use owo_colors::OwoColorize;
use tabled::{
grid::{
config::{ColoredConfig, Entity},
dimension::SpannedGridDimension,
records::{
vec_records::{Cell, VecRecords},
ExactRecords, PeekableRecords, Records,
},
util::string::string_width_multiline,
},
settings::{
object::{Columns, Object, Rows, Segment},
Alignment, CellOption, Color, Format, Margin, Modify, Padding, Style,
},
Table, Tabled,
};
#[derive(Tabled)]
#[tabled(rename_all = "PascalCase")]
struct Fundamental {
quantity: &'static str,
symbol: &'static str,
value: &'static str,
unit: &'static str,
}
impl Fundamental {
fn new(
quantity: &'static str,
symbol: &'static str,
value: &'static str,
unit: &'static str,
) -> Self {
Self {
quantity,
symbol,
value,
unit,
}
}
}
fn main() {
// data source: https://www.britannica.com/science/physical-constant
let data = [
Fundamental::new(
"constant of gravitation",
"G",
"6.67384 × 10⁻¹¹",
"cubic metre per second squared per kilogram",
),
Fundamental::new(
"speed of light (in a vacuum)",
"c",
"2.99792458 × 10⁻⁸",
"metres per second",
),
Fundamental::new(
"Planck's constant",
"h",
"6.626070040 × 10⁻³⁴",
"joule second",
),
Fundamental::new(
"Boltzmann constant",
"k",
"1.38064852 × 10⁻²³",
"joule per kelvin",
),
Fundamental::new(
"Faraday constant",
"F",
"9.648533289 × 10⁴",
"coulombs per mole",
),
];
let pane_color = Color::try_from(' '.bg_rgb::<220, 220, 220>().to_string()).unwrap();
let border_color = Color::try_from(' '.bg_rgb::<200, 200, 220>().bold().to_string()).unwrap();
let data_color = Color::try_from(' '.bg_rgb::<200, 200, 220>().to_string()).unwrap();
let header_settings = Modify::new(Rows::first())
.with(Padding::new(1, 1, 2, 2).colorize(
Color::BG_GREEN,
Color::BG_YELLOW,
Color::BG_MAGENTA,
Color::BG_CYAN,
))
.with(MakeMaxPadding)
.with(Format::content(|s| s.on_black().white().to_string()));
let data_settings = Modify::new(Rows::first().inverse())
.with(Alignment::left())
.with(MakeMaxPadding)
.with(Padding::new(1, 1, 0, 0).colorize(
Color::default(),
Color::default(),
data_color.clone(),
data_color.clone(),
));
let symbol_settings = Modify::new(Columns::single(1).not(Rows::first()))
.with(Format::content(|s| s.bold().to_string()));
let unit_settings = Modify::new(Columns::single(3).not(Rows::first()))
.with(Format::content(|s| s.italic().to_string()));
let table = Table::new(data)
.with(Style::rounded())
.with(Margin::new(1, 2, 1, 1).colorize(
pane_color.clone(),
pane_color.clone(),
pane_color.clone(),
pane_color,
))
.with(border_color)
.with(Modify::new(Segment::all()).with(data_color))
.with(header_settings)
.with(data_settings)
.with(symbol_settings)
.with(unit_settings)
.to_string();
println!("\n\n{table}\n\n");
}
#[derive(Debug, Clone)]
struct MakeMaxPadding;
impl<T> CellOption<VecRecords<T>, ColoredConfig> for MakeMaxPadding
where
T: Cell + AsRef<str>,
{
fn change(self, records: &mut VecRecords<T>, cfg: &mut ColoredConfig, entity: Entity) {
let widths = SpannedGridDimension::width(&*records, cfg);
let count_rows = records.count_rows();
let count_cols = records.count_columns();
for (row, col) in entity.iter(count_rows, count_cols) {
let column_width = widths[col];
let text = records.get_text((row, col));
let width = string_width_multiline(text);
if width < column_width {
let available_width = column_width - width;
let left = available_width / 2;
let right = available_width - left;
let pos = (row, col).into();
let mut pad = cfg.get_padding(pos);
pad.left.size = left;
pad.right.size = right;
cfg.set_padding(pos, pad);
}
}
}
}