Skip to content

Text and markup ​

willowui has two widgets for text:

WidgetUse it for
LabelOne style per widget: a title, a value, a caption. Cheap, and the right default.
RichTextMixed styles in one block: a bold word, a colored name, a link, an icon in a sentence, headings and bullet lists.

For text the player types, see TextInput, TextArea and RichTextEditor on the Text widgets page.

Label ​

new Label(name, text, family, size) makes a label. "default" is the built-in font family.

MethodDoes
setText(t)Changes the text.
setFont(family), setFontSize(size)Changes the font.
setBold(b), setItalic(b)Picks the bold or italic face of the family.
setColor(c)Overrides the theme's text color.
setAlign(a)TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER or TEXT_ALIGN_RIGHT.
setWrapWidth(w)Wraps lines at w pixels. 0 means no wrapping.
bindText(ref)Follows a Ref<string>. See Reactive state.

RichText and setMarkup ​

new RichText(name, family, size) makes the widget. setMarkup(text) parses a small XML-like markup and replaces the content. An unknown tag throws, so a typo fails loudly instead of showing raw tags.

TagDoes
<b>, <i>Bold, italic.
<u>, <strike>Underline, strikethrough.
<color value="#FFCC00">Text color. Takes the same color forms as themes: #RRGGBB, #RRGGBBAA, rgb(...), rgba(...), white, black, transparent.
<size value="24">Font size in pixels.
<outline thickness="2" color="#000000">A stroke behind the letters. Both attributes are optional (2 and black).
<span color="..." size="..." font="bold">Several at once. font is bold, italic, bolditalic or regular.
<link url="...">Underlined, clickable text. A click calls onLinkClick with the url.
<icon=sheet.png:3/>Frame 3 of a horizontal sprite sheet of icons, inline with the text.
<br/>Line break.
<h1>, <h2>, <h3>A bold heading on its own line, scaled 2, 1.5 and 1.2 times the base size. setHeadingScale(h1, h2, h3) changes the scales.
<ul>, <ol>, <li>Bullet and numbered lists, indented.

&amp;, &lt;, &gt;, &quot; and &apos; write the characters &, <, >, " and '.

Other methods: setWrapWidth(w), setAlign(a) (RICH_ALIGN_LEFT, RICH_ALIGN_CENTER, RICH_ALIGN_RIGHT, imported from "willowui"), setColor(c) and setOutline(o) for the defaults that tags override.

ts
import { DEFAULT_STAGE, Label, RichText, Screen, TEXT_ALIGN_CENTER } from "willowui";

const screen: Screen = new Screen();

const title: Label = new Label("title", "Quest log", "default", 22.0);
title.setPosition(20.0, 16.0);
title.setWrapWidth(400.0);
title.setAlign(TEXT_ALIGN_CENTER);
screen.add(title);

const log: RichText = new RichText("log", "default", 16.0);
log.setPosition(20.0, 60.0);
log.setWrapWidth(400.0);
log.setMarkup(
    "<h2>The lost lantern</h2>" +
    "Find <color value=\"#FFCC00\">Mira</color> by the <b>old mill</b>.<br/>" +
    "<ul><li>Bring <i>rope</i></li><li>Avoid the <outline thickness=\"2\">bog</outline></li></ul>" +
    "<link url=\"map:mill\">Show on map</link>"
);
log.onLinkClick = (url: string): void => { title.setText("Opening " + url); };
screen.add(log);

DEFAULT_STAGE.setScene(engine.root2d);
DEFAULT_STAGE.add(screen);
App.onFrame((dt: float): void => { DEFAULT_STAGE.update(dt); });

What the markup turns into ​

setMarkup is built on parseMarkup, which is exported too. It turns markup into a list of TextSpans, one per run of same-styled text. It needs no window, so it is a quick way to see what a string will do:

ts
import { TextSpan, parseMarkup } from "willowui";

const spans: TextSpan[] = parseMarkup("Press <b>Space</b> to <color value=\"#FFCC00\">jump</color>", null, 16.0, [2.0, 1.5, 1.2]);
for (const s of spans) {
    console.log("[" + s.text + "] bold=" + s.bold + " colored=" + s.colorSet);
}
try {
    parseMarkup("a <blink>b</blink>", null, 16.0, [2.0, 1.5, 1.2]);
} catch (e) {
    console.log((e as Error).message);
}

Output:

text
[Press ] bold=false colored=false
[Space] bold=true colored=false
[ to ] bold=false colored=false
[jump] bold=false colored=true
unknown markup tag <blink>

You can also build the spans yourself and pass them to setSpans(spans), or append with addSpan(text) and addTextSpan(span).

RichText in XML ​

In a template, write the markup as the element's children. markup="..." and bind:markup="..." work too, and on:linkClick names the controller method for links.

xml
<Panel layout="vbox" spacing="8" padding="16">
    <RichText fontSize="16" wrapWidth="360">
        <h2>Shop</h2>
        Gold: <color value="#FFD700">120</color>
        <ul><li>Potion</li><li>Ether</li></ul>
    </RichText>
</Panel>

Inline icons work the same way in a template: <icon=sheet.png:3/> inside <RichText> is passed to the markup parser as written.

See also ​

  • Text widgets: text input, text areas and the rich text editor.
  • Theming: the richText and label theme entries set the default colors.