pub struct Row {
pub children: Vec<Element>,
pub gap: f32,
pub align: Align,
pub common: Common,
}Fields§
§children: Vec<Element>§gap: f32§align: Align§common: CommonImplementations§
Source§impl Row
impl Row
Sourcepub fn new() -> Row
pub fn new() -> Row
Examples found in repository?
examples/invoice.rs (line 76)
35fn main() {
36 let mut items = vec![
37 LineItem {
38 description: "Beratungsleistung Projekt Alpha".to_string(),
39 qty: 8,
40 unit_price_cents: 12_000,
41 },
42 LineItem {
43 description: "Lizenz Software-Paket (jährlich)".to_string(),
44 qty: 1,
45 unit_price_cents: 49_900,
46 },
47 LineItem {
48 description: "Individuelle Anpassung / Customizing".to_string(),
49 qty: 3,
50 unit_price_cents: 15_000,
51 },
52 ];
53 // A few filler positions so the table is guaranteed to span more than
54 // one page, demonstrating the header-repeat-on-split behavior.
55 for i in 1..=25 {
56 items.push(LineItem {
57 description: format!("Zusatzposition {i:02}"),
58 qty: 1,
59 unit_price_cents: 990,
60 });
61 }
62
63 let net_total: i64 = items.iter().map(|i| i.qty as i64 * i.unit_price_cents).sum();
64 let vat_rate = 19;
65 let vat_total = net_total * vat_rate / 100;
66 let gross_total = net_total + vat_total;
67
68 let top_margin = 15.0 * MM;
69 let mut doc = Document::new(PageFormat::A4)
70 .margin(Margin::symmetric(20.0 * MM, top_margin))
71 .footer(Footer::new(30.0, |ctx| {
72 Column::new()
73 .gap(2.0)
74 .child(Line::new())
75 .child(
76 Row::new()
77 .gap(20.0)
78 .child(Text::new("Musterbank · IBAN DE12 3456 7890 1234 5678 90 · BIC MUSTDEFF").size(8.0))
79 .child(Text::new("USt-IdNr. DE123456789").size(8.0).flex(1.0)),
80 )
81 .child(Text::new(format!("Seite {} von {}", ctx.page, ctx.total_pages)).size(8.0))
82 .into()
83 }));
84
85 // --- DIN 5008 Form A window-envelope address block ----------------
86 // Window starts ~45mm from the top, ~20mm from the left
87 // (`plan/02-elementcatalog-and-features.md`); ~85x40mm matches a
88 // typical C6/5-long window envelope opening. Position/size are a
89 // documented convention for this recipe, not parsed from any norm
90 // document — a caller with different envelope stock adjusts these.
91 doc.add(Spacer::new(45.0 * MM - top_margin));
92 doc.add(
93 Column::new()
94 .gap(2.0)
95 .width(85.0 * MM)
96 .height(40.0 * MM)
97 .child(Text::new("Muster GmbH · Musterstraße 1 · 12345 Musterstadt").size(7.0))
98 .child(Spacer::new(8.0))
99 .child(Text::new("Empfänger GmbH"))
100 .child(Text::new("Frau Erika Mustermann"))
101 .child(Text::new("Beispielweg 42"))
102 .child(Text::new("54321 Beispielstadt")),
103 );
104 doc.add(Spacer::new(10.0 * MM));
105
106 doc.add(Text::new("Rechnung").heading1());
107 doc.add(Text::new(
108 "Rechnungsnummer: RE-2026-0142 Rechnungsdatum: 20.08.2026 Leistungsdatum: 20.08.2026",
109 ));
110 doc.add(Spacer::new(10.0));
111
112 doc.add(
113 Table::new()
114 .columns([
115 TableColumn::flex(1.0),
116 TableColumn::fixed(50.0).align(Align::End),
117 TableColumn::fixed(65.0).align(Align::End),
118 TableColumn::fixed(70.0).align(Align::End),
119 ])
120 .header(["Beschreibung", "Menge", "Einzelpreis", "Gesamt"])
121 .striped(Color::rgb(0xF5, 0xF5, 0xF5))
122 .from_rows(&items),
123 );
124
125 doc.add(Spacer::new(14.0));
126
127 // --- summary block (Netto/USt/Brutto), right-aligned --------------
128 // Recipe (`plan/02-elementcatalog-and-features.md`): an outer, full-
129 // width auto Column with `.align(Align::End)` positions the fixed-
130 // width (200pt) inner summary Column at the right edge; within it,
131 // each label gets `.flex(1.0)` to push its value to that block's own
132 // right edge. No special "summary block" element needed.
133 doc.add(
134 Column::new()
135 .align(Align::End)
136 .child(Column::new().gap(2.0).width(200.0).children(vec![
137 Element::from(
138 Row::new()
139 .child(Text::new("Nettosumme").flex(1.0))
140 .child(Text::new(format_currency_de(net_total))),
141 ),
142 Element::from(
143 Row::new()
144 .child(Text::new(format!("zzgl. {vat_rate}% USt.")).flex(1.0))
145 .child(Text::new(format_currency_de(vat_total))),
146 ),
147 Element::from(Line::new()),
148 Element::from(
149 Row::new()
150 .child(Text::new("Gesamtbetrag").bold().flex(1.0))
151 .child(Text::new(format_currency_de(gross_total)).bold()),
152 ),
153 ])),
154 );
155
156 common::write_pdf(&doc, "invoice.pdf");
157}Sourcepub fn child(self, child: impl Into<Element>) -> Row
pub fn child(self, child: impl Into<Element>) -> Row
Examples found in repository?
examples/invoice.rs (line 78)
35fn main() {
36 let mut items = vec![
37 LineItem {
38 description: "Beratungsleistung Projekt Alpha".to_string(),
39 qty: 8,
40 unit_price_cents: 12_000,
41 },
42 LineItem {
43 description: "Lizenz Software-Paket (jährlich)".to_string(),
44 qty: 1,
45 unit_price_cents: 49_900,
46 },
47 LineItem {
48 description: "Individuelle Anpassung / Customizing".to_string(),
49 qty: 3,
50 unit_price_cents: 15_000,
51 },
52 ];
53 // A few filler positions so the table is guaranteed to span more than
54 // one page, demonstrating the header-repeat-on-split behavior.
55 for i in 1..=25 {
56 items.push(LineItem {
57 description: format!("Zusatzposition {i:02}"),
58 qty: 1,
59 unit_price_cents: 990,
60 });
61 }
62
63 let net_total: i64 = items.iter().map(|i| i.qty as i64 * i.unit_price_cents).sum();
64 let vat_rate = 19;
65 let vat_total = net_total * vat_rate / 100;
66 let gross_total = net_total + vat_total;
67
68 let top_margin = 15.0 * MM;
69 let mut doc = Document::new(PageFormat::A4)
70 .margin(Margin::symmetric(20.0 * MM, top_margin))
71 .footer(Footer::new(30.0, |ctx| {
72 Column::new()
73 .gap(2.0)
74 .child(Line::new())
75 .child(
76 Row::new()
77 .gap(20.0)
78 .child(Text::new("Musterbank · IBAN DE12 3456 7890 1234 5678 90 · BIC MUSTDEFF").size(8.0))
79 .child(Text::new("USt-IdNr. DE123456789").size(8.0).flex(1.0)),
80 )
81 .child(Text::new(format!("Seite {} von {}", ctx.page, ctx.total_pages)).size(8.0))
82 .into()
83 }));
84
85 // --- DIN 5008 Form A window-envelope address block ----------------
86 // Window starts ~45mm from the top, ~20mm from the left
87 // (`plan/02-elementcatalog-and-features.md`); ~85x40mm matches a
88 // typical C6/5-long window envelope opening. Position/size are a
89 // documented convention for this recipe, not parsed from any norm
90 // document — a caller with different envelope stock adjusts these.
91 doc.add(Spacer::new(45.0 * MM - top_margin));
92 doc.add(
93 Column::new()
94 .gap(2.0)
95 .width(85.0 * MM)
96 .height(40.0 * MM)
97 .child(Text::new("Muster GmbH · Musterstraße 1 · 12345 Musterstadt").size(7.0))
98 .child(Spacer::new(8.0))
99 .child(Text::new("Empfänger GmbH"))
100 .child(Text::new("Frau Erika Mustermann"))
101 .child(Text::new("Beispielweg 42"))
102 .child(Text::new("54321 Beispielstadt")),
103 );
104 doc.add(Spacer::new(10.0 * MM));
105
106 doc.add(Text::new("Rechnung").heading1());
107 doc.add(Text::new(
108 "Rechnungsnummer: RE-2026-0142 Rechnungsdatum: 20.08.2026 Leistungsdatum: 20.08.2026",
109 ));
110 doc.add(Spacer::new(10.0));
111
112 doc.add(
113 Table::new()
114 .columns([
115 TableColumn::flex(1.0),
116 TableColumn::fixed(50.0).align(Align::End),
117 TableColumn::fixed(65.0).align(Align::End),
118 TableColumn::fixed(70.0).align(Align::End),
119 ])
120 .header(["Beschreibung", "Menge", "Einzelpreis", "Gesamt"])
121 .striped(Color::rgb(0xF5, 0xF5, 0xF5))
122 .from_rows(&items),
123 );
124
125 doc.add(Spacer::new(14.0));
126
127 // --- summary block (Netto/USt/Brutto), right-aligned --------------
128 // Recipe (`plan/02-elementcatalog-and-features.md`): an outer, full-
129 // width auto Column with `.align(Align::End)` positions the fixed-
130 // width (200pt) inner summary Column at the right edge; within it,
131 // each label gets `.flex(1.0)` to push its value to that block's own
132 // right edge. No special "summary block" element needed.
133 doc.add(
134 Column::new()
135 .align(Align::End)
136 .child(Column::new().gap(2.0).width(200.0).children(vec![
137 Element::from(
138 Row::new()
139 .child(Text::new("Nettosumme").flex(1.0))
140 .child(Text::new(format_currency_de(net_total))),
141 ),
142 Element::from(
143 Row::new()
144 .child(Text::new(format!("zzgl. {vat_rate}% USt.")).flex(1.0))
145 .child(Text::new(format_currency_de(vat_total))),
146 ),
147 Element::from(Line::new()),
148 Element::from(
149 Row::new()
150 .child(Text::new("Gesamtbetrag").bold().flex(1.0))
151 .child(Text::new(format_currency_de(gross_total)).bold()),
152 ),
153 ])),
154 );
155
156 common::write_pdf(&doc, "invoice.pdf");
157}pub fn children( self, children: impl IntoIterator<Item = impl Into<Element>>, ) -> Row
Sourcepub fn gap(self, gap: f32) -> Row
pub fn gap(self, gap: f32) -> Row
Examples found in repository?
examples/invoice.rs (line 77)
35fn main() {
36 let mut items = vec![
37 LineItem {
38 description: "Beratungsleistung Projekt Alpha".to_string(),
39 qty: 8,
40 unit_price_cents: 12_000,
41 },
42 LineItem {
43 description: "Lizenz Software-Paket (jährlich)".to_string(),
44 qty: 1,
45 unit_price_cents: 49_900,
46 },
47 LineItem {
48 description: "Individuelle Anpassung / Customizing".to_string(),
49 qty: 3,
50 unit_price_cents: 15_000,
51 },
52 ];
53 // A few filler positions so the table is guaranteed to span more than
54 // one page, demonstrating the header-repeat-on-split behavior.
55 for i in 1..=25 {
56 items.push(LineItem {
57 description: format!("Zusatzposition {i:02}"),
58 qty: 1,
59 unit_price_cents: 990,
60 });
61 }
62
63 let net_total: i64 = items.iter().map(|i| i.qty as i64 * i.unit_price_cents).sum();
64 let vat_rate = 19;
65 let vat_total = net_total * vat_rate / 100;
66 let gross_total = net_total + vat_total;
67
68 let top_margin = 15.0 * MM;
69 let mut doc = Document::new(PageFormat::A4)
70 .margin(Margin::symmetric(20.0 * MM, top_margin))
71 .footer(Footer::new(30.0, |ctx| {
72 Column::new()
73 .gap(2.0)
74 .child(Line::new())
75 .child(
76 Row::new()
77 .gap(20.0)
78 .child(Text::new("Musterbank · IBAN DE12 3456 7890 1234 5678 90 · BIC MUSTDEFF").size(8.0))
79 .child(Text::new("USt-IdNr. DE123456789").size(8.0).flex(1.0)),
80 )
81 .child(Text::new(format!("Seite {} von {}", ctx.page, ctx.total_pages)).size(8.0))
82 .into()
83 }));
84
85 // --- DIN 5008 Form A window-envelope address block ----------------
86 // Window starts ~45mm from the top, ~20mm from the left
87 // (`plan/02-elementcatalog-and-features.md`); ~85x40mm matches a
88 // typical C6/5-long window envelope opening. Position/size are a
89 // documented convention for this recipe, not parsed from any norm
90 // document — a caller with different envelope stock adjusts these.
91 doc.add(Spacer::new(45.0 * MM - top_margin));
92 doc.add(
93 Column::new()
94 .gap(2.0)
95 .width(85.0 * MM)
96 .height(40.0 * MM)
97 .child(Text::new("Muster GmbH · Musterstraße 1 · 12345 Musterstadt").size(7.0))
98 .child(Spacer::new(8.0))
99 .child(Text::new("Empfänger GmbH"))
100 .child(Text::new("Frau Erika Mustermann"))
101 .child(Text::new("Beispielweg 42"))
102 .child(Text::new("54321 Beispielstadt")),
103 );
104 doc.add(Spacer::new(10.0 * MM));
105
106 doc.add(Text::new("Rechnung").heading1());
107 doc.add(Text::new(
108 "Rechnungsnummer: RE-2026-0142 Rechnungsdatum: 20.08.2026 Leistungsdatum: 20.08.2026",
109 ));
110 doc.add(Spacer::new(10.0));
111
112 doc.add(
113 Table::new()
114 .columns([
115 TableColumn::flex(1.0),
116 TableColumn::fixed(50.0).align(Align::End),
117 TableColumn::fixed(65.0).align(Align::End),
118 TableColumn::fixed(70.0).align(Align::End),
119 ])
120 .header(["Beschreibung", "Menge", "Einzelpreis", "Gesamt"])
121 .striped(Color::rgb(0xF5, 0xF5, 0xF5))
122 .from_rows(&items),
123 );
124
125 doc.add(Spacer::new(14.0));
126
127 // --- summary block (Netto/USt/Brutto), right-aligned --------------
128 // Recipe (`plan/02-elementcatalog-and-features.md`): an outer, full-
129 // width auto Column with `.align(Align::End)` positions the fixed-
130 // width (200pt) inner summary Column at the right edge; within it,
131 // each label gets `.flex(1.0)` to push its value to that block's own
132 // right edge. No special "summary block" element needed.
133 doc.add(
134 Column::new()
135 .align(Align::End)
136 .child(Column::new().gap(2.0).width(200.0).children(vec![
137 Element::from(
138 Row::new()
139 .child(Text::new("Nettosumme").flex(1.0))
140 .child(Text::new(format_currency_de(net_total))),
141 ),
142 Element::from(
143 Row::new()
144 .child(Text::new(format!("zzgl. {vat_rate}% USt.")).flex(1.0))
145 .child(Text::new(format_currency_de(vat_total))),
146 ),
147 Element::from(Line::new()),
148 Element::from(
149 Row::new()
150 .child(Text::new("Gesamtbetrag").bold().flex(1.0))
151 .child(Text::new(format_currency_de(gross_total)).bold()),
152 ),
153 ])),
154 );
155
156 common::write_pdf(&doc, "invoice.pdf");
157}pub fn align(self, align: Align) -> Row
pub fn width(self, width: f32) -> Row
pub fn height(self, height: f32) -> Row
pub fn flex(self, factor: f32) -> Row
pub fn padding(self, padding: f32) -> Row
pub fn corner_radius(self, radius: f32) -> Row
pub fn overflow(self, overflow: Overflow) -> Row
pub fn background(self, color: Color) -> Row
pub fn border(self, border: Border) -> Row
Sourcepub fn keep_with_next(self) -> Row
pub fn keep_with_next(self) -> Row
See plan/05-overflow-and-robustness.md Grundprinzip 9: only
placed on a page if the following sibling also still fits.
Trait Implementations§
Source§impl Layoutable for Row
impl Layoutable for Row
fn measure(&self, ctx: &LayoutCtx<'_>, constraints: Constraints) -> Size
fn layout( &self, ctx: &LayoutCtx<'_>, area: Rect, warnings: &mut Vec<LayoutWarning>, page: usize, ) -> LayoutResult
Auto Trait Implementations§
impl Freeze for Row
impl RefUnwindSafe for Row
impl Send for Row
impl Sync for Row
impl Unpin for Row
impl UnsafeUnpin for Row
impl UnwindSafe for Row
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more