use std::fmt::{self, Debug, Formatter};
use crate::diag::{bail, SourceResult};
use crate::engine::Engine;
use crate::foundations::{
elem, scope, Args, Cast, Construct, Content, NativeElement, Packed, Set, Smart,
StyleVec, Unlabellable,
};
use crate::introspection::{Count, CounterUpdate, Locatable};
use crate::layout::{Em, HAlignment, Length, OuterHAlignment};
use crate::model::Numbering;
use crate::utils::singleton;
#[elem(scope, title = "Paragraph", Debug, Construct)]
pub struct ParElem {
#[resolve]
#[ghost]
#[default(Em::new(0.65).into())]
pub leading: Length,
#[resolve]
#[ghost]
#[default(Em::new(1.2).into())]
pub spacing: Length,
#[ghost]
#[default(false)]
pub justify: bool,
#[ghost]
pub linebreaks: Smart<Linebreaks>,
#[ghost]
pub first_line_indent: Length,
#[ghost]
#[resolve]
pub hanging_indent: Length,
#[ghost]
#[internal]
#[default(true)]
pub shrink: bool,
#[external]
#[required]
pub body: Content,
#[internal]
#[variadic]
pub children: StyleVec,
}
#[scope]
impl ParElem {
#[elem]
type ParLine;
}
impl Construct for ParElem {
fn construct(engine: &mut Engine, args: &mut Args) -> SourceResult<Content> {
let styles = Self::set(engine, args)?;
let body = args.expect::<Content>("body")?;
Ok(Content::sequence([
ParbreakElem::shared().clone(),
body.styled_with_map(styles),
ParbreakElem::shared().clone(),
]))
}
}
impl Debug for ParElem {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Par ")?;
self.children.fmt(f)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)]
pub enum Linebreaks {
Simple,
Optimized,
}
#[elem(title = "Paragraph Break", Unlabellable)]
pub struct ParbreakElem {}
impl ParbreakElem {
pub fn shared() -> &'static Content {
singleton!(Content, ParbreakElem::new().pack())
}
}
impl Unlabellable for Packed<ParbreakElem> {}
#[elem(name = "line", title = "Paragraph Line", keywords = ["line numbering"], Construct, Locatable)]
pub struct ParLine {
#[ghost]
pub numbering: Option<Numbering>,
#[ghost]
pub number_align: Smart<HAlignment>,
#[ghost]
#[default(OuterHAlignment::Start)]
pub number_margin: OuterHAlignment,
#[ghost]
#[default]
pub number_clearance: Smart<Length>,
#[ghost]
#[default(LineNumberingScope::Document)]
pub numbering_scope: LineNumberingScope,
}
impl Construct for ParLine {
fn construct(_: &mut Engine, args: &mut Args) -> SourceResult<Content> {
bail!(args.span, "cannot be constructed manually");
}
}
#[derive(Debug, Cast, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LineNumberingScope {
Document,
Page,
}
#[elem(Construct, Locatable, Count)]
pub struct ParLineMarker {
#[internal]
#[required]
pub numbering: Numbering,
#[internal]
#[required]
pub number_align: Smart<HAlignment>,
#[internal]
#[required]
pub number_margin: OuterHAlignment,
#[internal]
#[required]
pub number_clearance: Smart<Length>,
}
impl Construct for ParLineMarker {
fn construct(_: &mut Engine, args: &mut Args) -> SourceResult<Content> {
bail!(args.span, "cannot be constructed manually");
}
}
impl Count for Packed<ParLineMarker> {
fn update(&self) -> Option<CounterUpdate> {
None
}
}