|
| 1 | +package com.demcha.examples.features.layout; |
| 2 | + |
| 3 | +import com.demcha.compose.GraphCompose; |
| 4 | +import com.demcha.compose.document.api.DocumentSession; |
| 5 | +import com.demcha.compose.document.node.HorizontalAlign; |
| 6 | +import com.demcha.compose.document.style.DocumentColor; |
| 7 | +import com.demcha.compose.document.style.DocumentInsets; |
| 8 | +import com.demcha.compose.document.style.DocumentStroke; |
| 9 | +import com.demcha.compose.document.style.DocumentTextStyle; |
| 10 | +import com.demcha.compose.document.svg.SvgIcon; |
| 11 | +import com.demcha.examples.support.ExampleOutputPaths; |
| 12 | + |
| 13 | +import java.nio.file.Path; |
| 14 | + |
| 15 | +/** |
| 16 | + * Runnable showcase for v1.8 block-level horizontal alignment: a fixed-size |
| 17 | + * node (an SVG icon, a vector path, …) placed LEFT / CENTER / RIGHT within the |
| 18 | + * page content width with one call — the {@code margin: auto} the flow does not |
| 19 | + * give fixed nodes on its own. |
| 20 | + * |
| 21 | + * <pre>{@code |
| 22 | + * flow.addSvgIcon(icon, 48, HorizontalAlign.CENTER); |
| 23 | + * flow.addAligned(HorizontalAlign.RIGHT, anyFixedNode); |
| 24 | + * }</pre> |
| 25 | + * |
| 26 | + * @author Artem Demchyshyn |
| 27 | + */ |
| 28 | +public final class BlockAlignExample { |
| 29 | + |
| 30 | + private static final DocumentColor INK = DocumentColor.rgb(34, 38, 50); |
| 31 | + private static final DocumentColor TEAL = DocumentColor.rgb(20, 80, 95); |
| 32 | + |
| 33 | + /** Inline two-tone badge so the example needs no icon resource. */ |
| 34 | + private static final String BADGE_SVG = """ |
| 35 | + <svg viewBox="0 0 24 24"> |
| 36 | + <circle cx="12" cy="12" r="11" fill="#fde9e3"/> |
| 37 | + <path fill="#c41e3a" d="M12 2 L22 12 L12 22 L2 12 Z"/> |
| 38 | + </svg> |
| 39 | + """; |
| 40 | + |
| 41 | + private BlockAlignExample() { |
| 42 | + } |
| 43 | + |
| 44 | + /** |
| 45 | + * Renders the alignment sheet: one icon and one path, each shown |
| 46 | + * left / centre / right aligned. |
| 47 | + * |
| 48 | + * @return path to the generated PDF |
| 49 | + * @throws Exception if rendering or file IO fails |
| 50 | + */ |
| 51 | + public static Path generate() throws Exception { |
| 52 | + Path pdfFile = ExampleOutputPaths.prepare("features/layout", "block-align.pdf"); |
| 53 | + |
| 54 | + SvgIcon icon = SvgIcon.parse(BADGE_SVG); |
| 55 | + DocumentTextStyle caption = DocumentTextStyle.DEFAULT.withSize(10).withColor(INK); |
| 56 | + |
| 57 | + try (DocumentSession document = GraphCompose.document(pdfFile) |
| 58 | + .pageSize(420, 400) |
| 59 | + .margin(DocumentInsets.of(28)) |
| 60 | + .create()) { |
| 61 | + document.pageFlow(page -> { |
| 62 | + page.addParagraph(p -> p |
| 63 | + .text("Block alignment") |
| 64 | + .textStyle(DocumentTextStyle.DEFAULT.withSize(20))); |
| 65 | + page.addParagraph(p -> p |
| 66 | + .text("A fixed-size node left-aligns in the flow by default. " |
| 67 | + + "addSvgIcon(icon, w, align) / addAligned(align, node) seats it " |
| 68 | + + "left, centre, or right across the content width — no manual maths.") |
| 69 | + .textStyle(DocumentTextStyle.DEFAULT.withSize(9.5) |
| 70 | + .withColor(DocumentColor.rgb(90, 96, 105))) |
| 71 | + .padding(DocumentInsets.bottom(8))); |
| 72 | + |
| 73 | + for (HorizontalAlign align : HorizontalAlign.values()) { |
| 74 | + page.addParagraph(p -> p |
| 75 | + .text("addSvgIcon(icon, 44, HorizontalAlign." + align + ")") |
| 76 | + .textStyle(caption) |
| 77 | + .padding(DocumentInsets.top(6))); |
| 78 | + page.addSvgIcon(icon, 44, align); |
| 79 | + } |
| 80 | + |
| 81 | + page.addParagraph(p -> p |
| 82 | + .text("addAligned(CENTER, anyNode) — works for any fixed node, e.g. a path") |
| 83 | + .textStyle(caption) |
| 84 | + .padding(DocumentInsets.top(10))); |
| 85 | + page.addAligned(HorizontalAlign.CENTER, chevron()); |
| 86 | + }); |
| 87 | + |
| 88 | + document.buildPdf(); |
| 89 | + } |
| 90 | + |
| 91 | + return pdfFile; |
| 92 | + } |
| 93 | + |
| 94 | + /** A small stroked chevron path to show alignment is not icon-specific. */ |
| 95 | + private static com.demcha.compose.document.node.DocumentNode chevron() { |
| 96 | + return new com.demcha.compose.document.dsl.PathBuilder() |
| 97 | + .name("Chevron") |
| 98 | + .size(60, 30) |
| 99 | + .moveTo(0.0, 1.0).lineTo(0.5, 0.0).lineTo(1.0, 1.0) |
| 100 | + .stroke(DocumentStroke.of(TEAL, 4)) |
| 101 | + .lineCap(com.demcha.compose.document.style.DocumentLineCap.ROUND) |
| 102 | + .lineJoin(com.demcha.compose.document.style.DocumentLineJoin.ROUND) |
| 103 | + .build(); |
| 104 | + } |
| 105 | + |
| 106 | + public static void main(String[] args) throws Exception { |
| 107 | + System.out.println("Generated: " + generate()); |
| 108 | + } |
| 109 | +} |
0 commit comments