ForgeCrowdBookWe don't sell the fish – we give you the rod.

Solutions

Solutions to the exercises. Each solution is also a complete project in the examples folder of the CrowdWare books repository.


Your First App

Project: examples/first-app-solution

app.sml – a second button below the first:

        Button {
            id: btnReset
            text: "Reset"
        }

app.sms – one more handler:

on btnReset.clicked() {
    clicks = 0
    greeting.text = "Hello, Forge!"
}

And the title, for example:

    title: "Adam's First Forge App"

Because clicks lives at the top of the script, both handlers see the same counter. Press Say hello twice, then Reset, then Say hello again – the label says Hello for the 1. time!


Nodes, Properties and Values

Project: examples/business-card-solution

app.sml – a second hidden label, and the bar at 100 without its text:

            Label {
                id: secret2
                text: "Favourite place: the sea"
                color: "#9DB8F2"
                visible: false
            }

            // How much coffee is left today, in percent
            ProgressBar { id: coffee value: 100 showPercentage: false }

app.sms – one handler switches on both:

on btnMore.clicked() {
    secret.visible = true
    secret2.visible = true
}

showPercentage: false hides the number but keeps the bar. With value: 100 the bar is full – and without the text it becomes a thin line, because the text was what made it tall.


Layout

Project: examples/keypad-solution

Window {
    id: mainWindow
    title: "Keypad"
    size: 300, 400

    VBoxContainer {
        anchors: left | top | right | bottom
        padding: 12, 12, 12, 12
        spacing: 8

        Label { id: display text: "0" fontSize: 32 align: right }

        GridContainer {
            columns: 3
            spacing: 6
            sizeFlagsVertical: expandFill

            Button { text: "7" sizeFlagsHorizontal: expandFill sizeFlagsVertical: expandFill }
            Button { text: "8" sizeFlagsHorizontal: expandFill sizeFlagsVertical: expandFill }
            Button { text: "9" sizeFlagsHorizontal: expandFill sizeFlagsVertical: expandFill }
            Button { text: "4" sizeFlagsHorizontal: expandFill sizeFlagsVertical: expandFill }
            Button { text: "5" sizeFlagsHorizontal: expandFill sizeFlagsVertical: expandFill }
            Button { text: "6" sizeFlagsHorizontal: expandFill sizeFlagsVertical: expandFill }
            Button { text: "1" sizeFlagsHorizontal: expandFill sizeFlagsVertical: expandFill }
            Button { text: "2" sizeFlagsHorizontal: expandFill sizeFlagsVertical: expandFill }
            Button { text: "3" sizeFlagsHorizontal: expandFill sizeFlagsVertical: expandFill }
            Button { text: "C" sizeFlagsHorizontal: expandFill sizeFlagsVertical: expandFill }
            Button { text: "0" sizeFlagsHorizontal: expandFill sizeFlagsVertical: expandFill }
            Button { text: "=" sizeFlagsHorizontal: expandFill sizeFlagsVertical: expandFill }
        }
    }
}

The keypad

Two things make the keypad fill the window. The GridContainer asks the outer VBoxContainer for all free height (sizeFlagsVertical: expandFill). And every button asks the grid for free space in both directions. Without the flags on the buttons, the grid would grow, but the buttons would stay small in the top-left of their cells.


Resources and Themes

Project: examples/welcome-solution

strings-es.sml – a new file, with every name of strings.sml:

Strings {
    windowTitle: "Bienvenido"
    headline: "Bienvenido a Forge"
    intro: "Este texto viene de strings-es.sml."
    btnLight: "Claro"
    btnDark: "Oscuro"
    btnSepia: "Sepia"
    themeChanged: "Tema cambiado"
    notThere: "Ahora viene de strings-es.sml"
}

strings.sml and strings-de.sml get the two new names too:

    btnSepia: "Sepia"
    notThere: "Now it comes from strings.sml"
    btnSepia: "Sepia"
    notThere: "Jetzt kommt er aus strings-de.sml"

theme.sepia.sml – the third set of colours, same names as the others:

Colors {
    brand: "#7A3E12"
    surface: "#E9D8B4"
    text: "#3B2A1A"
}

app.sml – the third button, and the label without its fallback:

                Label { id: missing text: @Strings.notThere color: @Colors.text }
                    Button { id: btnSepia text: @Strings.btnSepia }

app.sms – one more handler:

on btnSepia.clicked() {
    ui.setTheme("sepia")
    log.info(i18n.tr("themeChanged"))
}

Spanish, dark and sepia

Not one line of app.sml names a language or a colour. A fourth language or a fourth theme would again be one new file and, for the theme, one button.