Kawa
Elements

Layout Elements

Column, Row, Grid, Container, and Stack for arranging content on a page.

ColumnElement

ColumnElement stacks elements vertically. It is the default container you work with inside content(), header(), and footer() callbacks.

ColumnElement col = new ColumnElement(c -> {
    c.text("Title").bold().fontSize(14);
    c.add(new SpacerElement(8));
    c.text("Body text goes here.");
});

Use .spacing(float) to add a uniform gap between all children instead of adding spacers manually:

new ColumnElement(c -> {
    c.text("Line 1");
    c.text("Line 2");
    c.text("Line 3");
}).spacing(6);

Both accept an optional Unit:

new SpacerElement(5, Unit.MM)
col.spacing(3, Unit.MM)

RowElement

RowElement arranges children side by side. You define each column with one of these methods:

MethodWhat it does
.fixedColumn(float, ...)Adds a column with an exact width in points
.fixedColumn(float, Unit, ...)Adds a column with an exact width in the given unit
.relativeColumn(float, ...)Adds a proportional column; weight 2 gets twice the space of weight 1
.fillColumn(...)Shorthand for .relativeColumn(1, ...)
.spacing(float)Sets the gap between columns in points
.spacing(float, Unit)Sets the gap in the given unit
c.item().row(row -> {
    row.fixedColumn(28, Unit.MM, col -> col.text("Label:").semiBold());
    row.fillColumn(               col -> col.text("Value"));
    row.fixedColumn(16, Unit.MM,  col -> col.text("Unit").fontSize(9).color(Colors.GRAY_500));
});

GridElement

GridElement is a two-dimensional grid. You define the column structure once and then add rows:

c.add(new GridElement(grid -> {
    grid.columns(cols -> {
        cols.fixed(90);       // label column — points
        cols.fixed(32, Unit.MM); // or with a unit
        cols.relative(1);     // value column
    });
    grid.rowGap(6);

    grid.row(r -> {
        r.cell(col -> col.text("Name:").semiBold().fontSize(10));
        r.cell(col -> col.text("Max Mustermann").fontSize(10));
    });
    grid.row(r -> {
        r.cell(col -> col.text("Email:").semiBold().fontSize(10));
        r.cell(col -> col.text("max@example.com").fontSize(10));
    });
}));

Control spacing with grid.columnGap(float) and grid.rowGap(float).

ContainerElement

ContainerElement wraps another element with a background color, padding, and borders. You can create one inline or from a reusable StyleSheet:

// Inline
ContainerElement.of(s -> s
    .background(Colors.BLUE_50)
    .padding(12f)
    .border(1f, Colors.BLUE_200)
).containing(
    new TextElement("Info box").semiBold().color(Colors.BLUE_900)
);

// With units
ContainerElement.of(s -> s
    .background(Colors.GRAY_50)
    .padding(4, Unit.MM)
    .border(0.5f, Unit.MM, Colors.GRAY_200)
).containing(myElement);

// Reusable style
StyleSheet cardStyle = StyleSheet.of(s -> s
    .background(Colors.GRAY_50)
    .paddingH(16f).paddingV(12f)
    .border(0.5f, Colors.GRAY_200)
);

c.add(ContainerElement.of(cardStyle).containing(myElement));

See StyleSheet for the full list of styling options.

StackElement

StackElement renders multiple layers on top of each other, all aligned to the same top-left corner. The height of the stack equals the height of its tallest layer.

A typical use case is placing a badge or label over a colored background block:

c.add(new StackElement()
    .layer(new SpacerElement(60))
    .layer(new ColumnElement(col -> {
        col.text("RECOMMENDED").bold().fontSize(8).color(Colors.WHITE).centerAlign();
        col.text("9,900 EUR").bold().fontSize(20).centerAlign();
    }))
);

You can also use it for a draft watermark:

c.add(new StackElement()
    .layer(bodyContent)
    .layer(new ColumnElement(col ->
        col.text("DRAFT").fontSize(48).bold()
           .color(Colors.GRAY_300.withAlpha(0.4f))
           .centerAlign()
    ))
);

On this page