use crate::{
color::{Alpha, Channel, Channels},
error::NotcursesResult as Result,
plane::{Plane, Style},
sys::NcCell,
};
#[derive(Clone, Copy, Default, PartialEq, Eq)]
#[repr(transparent)]
pub struct Cell {
nc: NcCell,
}
mod core_impls {
use super::{Cell, Channels, NcCell, Style};
use core::fmt;
impl fmt::Display for Cell {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let width = self.nc.width;
let egc = if let Some(s) = self.try_egc() {
format!["\"{s}\""]
} else {
"&ref".into()
};
let style = Style::from(self.nc.stylemask);
let channels = Channels::from(self.nc.channels);
write!(f, "{egc} {width} {style} {channels}")
}
}
impl fmt::Debug for Cell {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let width = self.nc.width;
let egc = if let Some(s) = self.try_egc() {
format!["\"{s}\""]
} else {
"&ref".into()
};
let style = Style::from(self.nc.stylemask);
let channels = Channels::from(self.nc.channels);
write!(f, "Cell {{{egc:} width:{width} {style:?} {channels}}}")
}
}
impl From<NcCell> for Cell {
fn from(nc: NcCell) -> Cell {
Self { nc }
}
}
impl From<Cell> for NcCell {
fn from(c: Cell) -> NcCell {
c.nc
}
}
impl<'c> From<&'c Cell> for &'c NcCell {
fn from(c: &'c Cell) -> &'c NcCell {
&c.nc
}
}
}
impl Cell {
pub fn new() -> Cell {
NcCell::new().into()
}
pub fn from_str(plane: &mut Plane, string: &str) -> Result<Cell> {
Ok(NcCell::from_str(plane.into_ref_mut(), string)?.into())
}
}
impl Cell {
#[inline]
pub const fn uses_egcpool(&self) -> bool {
self.nc.gcluster >> 24 == 0x01
}
pub fn try_egc(&self) -> Option<String> {
if self.uses_egcpool() {
None
} else {
let bytes = self.nc.gcluster.to_ne_bytes();
let no_nuls = bytes.split(|b| *b == 0).next().unwrap();
core::str::from_utf8(no_nuls).ok().map(|s| s.to_string())
}
}
pub fn egc(&self, plane: &mut Plane) -> &str {
self.nc.egc(plane.into_ref_mut())
}
}
impl Cell {
pub fn channels(&self) -> Channels {
self.nc.channels().into()
}
pub fn fg(&self) -> Channel {
self.nc.fchannel().into()
}
pub fn bg(&self) -> Channel {
self.nc.bchannel().into()
}
pub fn set_channels(&mut self, channels: impl Into<Channels>) -> Channels {
let prev = self.channels();
self.nc.set_channels(channels.into());
prev
}
pub fn set_fg(&mut self, channel: impl Into<Channel>) -> Channel {
let fg = self.fg();
self.nc.set_fchannel(channel.into());
fg
}
pub fn set_bg(&mut self, channel: impl Into<Channel>) -> Channel {
let bg = self.fg();
self.nc.set_bchannel(channel.into());
bg
}
pub fn cset_channels(mut self, channels: impl Into<Channels>) -> Self {
self.nc.set_channels(channels.into());
self
}
pub fn cset_fg(mut self, channel: impl Into<Channel>) -> Self {
self.nc.set_fchannel(channel.into());
self
}
pub fn cset_bg(mut self, channel: impl Into<Channel>) -> Self {
self.nc.set_bchannel(channel.into());
self
}
}
impl Cell {
pub fn fg_alpha(&self) -> Alpha {
self.nc.fg_alpha().into()
}
pub fn bg_alpha(&self) -> Alpha {
self.nc.bg_alpha().into()
}
pub fn set_fg_alpha(&mut self, foreground: Alpha) -> Alpha {
let prev = self.fg_alpha();
self.nc.set_fg_alpha(foreground);
prev
}
pub fn set_bg_alpha(&mut self, background: Alpha) -> Alpha {
let prev = self.bg_alpha();
self.nc.set_bg_alpha(background);
prev
}
}
impl Cell {
pub fn styles(&self) -> Style {
self.nc.styles().into()
}
pub fn set_styles(&mut self, styles: impl Into<Style>) -> Style {
let prev = self.styles();
self.nc.styles_set(styles.into());
prev
}
pub fn add_styles(&mut self, styles: impl Into<Style>) -> Style {
let prev = self.styles();
self.nc.styles_on(styles.into());
prev
}
pub fn del_styles(&mut self, styles: impl Into<Style>) -> Style {
let prev = self.styles();
self.nc.styles_off(styles.into());
prev
}
pub fn cset_style(mut self, styles: impl Into<Style>) -> Self {
self.nc.styles_set(styles.into());
self
}
}