Hi! I am trying to create a simple Tic Tac Toe. I ...
# doodle
n
Hi! I am trying to create a simple Tic Tac Toe. I am creating my custom View called Cell, which is basically a rectangle with a text on it, but I can't make the size of the text equal to the size of the rectangle. Could anybody help me, please?
Copy code
class TicTacToe(display: Display, textMetrics: TextMetrics) : Application {

    private var playerMoves = Player.X

    private fun getPlayerName(): String {
        val playerName = playerMoves.toString()
        playerMoves = playerMoves.next
        return playerName
    }
    init {

        val panel = GridPanel().apply {
            rowSpacing         = { 10.0 }
            columnSpacing      = { 10.0 }
            rowSizingPolicy    = FitPanel // FitContent, or custom policy
            columnSizingPolicy = FitPanel // FitContent, or custom policy


            for (i in 0..2)
                for (j in 0..2) {
                    add(Cell(textMetrics, ::getPlayerName), row = i, column = j)
                }

            val panelSize = min(display.width, display.height) * 0.8
            size = Size(panelSize, panelSize)
            Resizer(this).apply { movable = false }

        }

        display += panel
        display.layout = constrain(display.first(), center)
    }

    override fun shutdown() {}
}

class Cell(textMetrics: TextMetrics, getPlayerName: () -> String) : View() {

    var text by renderProperty("")

    init {
        this.pointerChanged += object : PointerListener {

            override fun clicked(event: PointerEvent) {
                if (text.isEmpty()) text = getPlayerName()
            }
        }
    }
    override fun render(canvas: Canvas) {
        canvas.rect(bounds.atOrigin, Blue.lighter(0.4f))

        canvas.text(text, at = Point(width / 2, height / 2), color = White)
    }

}

enum class Player {
    X {
        override fun toString(): String {
            return "X";
        }
    },

    O {
        override fun toString(): String {
            return "O";
        }
    };

    val next
        get() = if (this == X) O else X
}

fun main() {

    application(modules = listOf(PointerModule)) {
        TicTacToe(display = instance(), textMetrics = instance())
    }
}
n
Hey. You can make the text scale by using a transform on the Canvas during render. These are AffineTransforms that let you scale, translate, rotate, etc.. This is the easiest way to get what you want. Here's how you might do that.
Copy code
class Cell(textMetrics: TextMetrics, getPlayerName: () -> String) : View() {

    var textSize by renderProperty(Empty) // renderProperty so you repaint if the size updates

    // could use a simple observable since you get repaint when textSize is updated
    var text by observable("") { _, new -> 
        textSize = textMetrics.size(new)
    }

    init {
        pointerChanged += clicked {
            if (text.isEmpty()) text = getPlayerName()
        }
    }

    override fun render(canvas: Canvas) {
        // calculate the scale factor: half of the smaller side
        val scaleFactor = (min(width, height) * 0.5) / textSize.width

        canvas.rect(bounds.atOrigin, Blue.lighter(0.4f))

        // scale the canvas and perform the text rendering. scale only applies in the following block
        canvas.scale(around = Point(width/2, height/2), x = scaleFactor, y = scaleFactor) {
            // text here will be scaled
            text(text, at = Point((width - textSize.width) / 2, (height - textSize.height) / 2), fill = White.paint)
        }
    }
}