Skip to content

Commit

Permalink
Merge pull request #371 from nanodeath/box-title-alignment
Browse files Browse the repository at this point in the history
Box title alignment support
  • Loading branch information
adam-arold authored Apr 24, 2021
2 parents 4b6a650 + 153c4f4 commit 8441af2
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package org.hexworks.zircon.api
import org.hexworks.cobalt.databinding.api.extension.createPropertyFrom
import org.hexworks.zircon.api.component.Component
import org.hexworks.zircon.api.component.renderer.ComponentDecorationRenderer
import org.hexworks.zircon.api.component.renderer.ComponentDecorationRenderer.Alignment
import org.hexworks.zircon.api.component.renderer.ComponentDecorationRenderer.RenderingMode
import org.hexworks.zircon.api.component.renderer.ComponentDecorationRenderer.RenderingMode.NON_INTERACTIVE
import org.hexworks.zircon.api.graphics.BoxType
Expand Down Expand Up @@ -42,11 +43,13 @@ object ComponentDecorations {
fun box(
boxType: BoxType = BoxType.SINGLE,
title: String = "",
renderingMode: RenderingMode = NON_INTERACTIVE
renderingMode: RenderingMode = NON_INTERACTIVE,
titleAlignment: Alignment = Alignment.TOP_LEFT
): ComponentDecorationRenderer = BoxDecorationRenderer(
boxType = boxType,
titleProperty = createPropertyFrom(title),
renderingMode = renderingMode
renderingMode = renderingMode,
titleAlignment = titleAlignment
)

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.hexworks.zircon.api.component.renderer

import org.hexworks.zircon.api.component.data.ComponentState
import org.hexworks.zircon.api.component.renderer.ComponentDecorationRenderer.Alignment
import org.hexworks.zircon.api.component.renderer.ComponentDecorationRenderer.RenderingMode.INTERACTIVE
import org.hexworks.zircon.api.component.renderer.ComponentDecorationRenderer.RenderingMode.NON_INTERACTIVE
import org.hexworks.zircon.api.data.Position
Expand Down Expand Up @@ -33,4 +34,37 @@ interface ComponentDecorationRenderer : DecorationRenderer<ComponentDecorationRe
enum class RenderingMode {
INTERACTIVE, NON_INTERACTIVE
}

/**
* Alignment for decorator attributes like box title.
*/
enum class Alignment {
TOP_LEFT,
TOP_CENTER,
TOP_RIGHT,
BOTTOM_LEFT,
BOTTOM_CENTER,
BOTTOM_RIGHT
}
}

internal fun Alignment.isLeft() = when(this) {
Alignment.TOP_LEFT, Alignment.BOTTOM_LEFT -> true
else -> false
}
internal fun Alignment.isRight() = when(this) {
Alignment.TOP_RIGHT, Alignment.BOTTOM_RIGHT -> true
else -> false
}
internal fun Alignment.isCenter() = when(this) {
Alignment.TOP_CENTER, Alignment.BOTTOM_CENTER -> true
else -> false
}
internal fun Alignment.isTop() = when (this) {
Alignment.TOP_LEFT, Alignment.TOP_RIGHT, Alignment.TOP_CENTER -> true
else -> false
}
internal fun Alignment.isBottom() = when (this) {
Alignment.BOTTOM_LEFT, Alignment.BOTTOM_RIGHT, Alignment.BOTTOM_CENTER -> true
else -> false
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import org.hexworks.cobalt.databinding.api.property.Property
import org.hexworks.zircon.api.behavior.TitleOverride
import org.hexworks.zircon.api.builder.data.TileBuilder
import org.hexworks.zircon.api.builder.graphics.BoxBuilder
import org.hexworks.zircon.api.component.renderer.ComponentDecorationRenderContext
import org.hexworks.zircon.api.component.renderer.ComponentDecorationRenderer
import org.hexworks.zircon.api.component.renderer.*
import org.hexworks.zircon.api.component.renderer.ComponentDecorationRenderer.Alignment
import org.hexworks.zircon.api.component.renderer.ComponentDecorationRenderer.RenderingMode
import org.hexworks.zircon.api.component.renderer.ComponentDecorationRenderer.RenderingMode.NON_INTERACTIVE
import org.hexworks.zircon.api.component.renderer.isRight
import org.hexworks.zircon.api.component.renderer.isTop
import org.hexworks.zircon.api.data.Position
import org.hexworks.zircon.api.data.Size
import org.hexworks.zircon.api.graphics.BoxType
Expand All @@ -17,7 +19,8 @@ import org.hexworks.zircon.api.graphics.TileGraphics
data class BoxDecorationRenderer(
val boxType: BoxType = BoxType.SINGLE,
private val titleProperty: Property<String> = createPropertyFrom(""),
private val renderingMode: RenderingMode = NON_INTERACTIVE
private val renderingMode: RenderingMode = NON_INTERACTIVE,
private val titleAlignment: Alignment = Alignment.TOP_LEFT
) : ComponentDecorationRenderer {

override val offset = Position.offset1x1()
Expand Down Expand Up @@ -47,13 +50,24 @@ data class BoxDecorationRenderer(
} else {
finalTitle
}
val titleOffsetX = when {
titleAlignment.isLeft() -> 0
titleAlignment.isRight() -> size.width - cleanText.length - 4
titleAlignment.isCenter() -> (size.width - cleanText.length - 4) / 2
else -> throw IllegalStateException("unreachable")
}
val titleOffsetY = when {
titleAlignment.isTop() -> 0
titleAlignment.isBottom() -> size.height - 1
else -> throw IllegalStateException("unreachable")
}
tileGraphics.draw(
TileBuilder.newBuilder()
.withStyleSet(style)
.withCharacter(boxType.connectorLeft)
.build(), Position.create(1, 0)
.build(), Position.create(1 + titleOffsetX, titleOffsetY)
)
val pos = Position.create(2, 0)
val pos = Position.create(2 + titleOffsetX, titleOffsetY)
(cleanText.indices).forEach { idx ->
tileGraphics.draw(
tile = TileBuilder.newBuilder()
Expand All @@ -68,7 +82,7 @@ data class BoxDecorationRenderer(
.withStyleSet(style)
.withCharacter(boxType.connectorRight)
.build(),
drawPosition = Position.create(2 + cleanText.length, 0)
drawPosition = Position.create(2 + titleOffsetX + cleanText.length, titleOffsetY)
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package org.hexworks.zircon.internal.component.renderer.decoration

import org.assertj.core.api.Assertions.assertThat
import org.hexworks.zircon.api.CP437TilesetResources
import org.hexworks.zircon.api.ComponentDecorations.box
import org.hexworks.zircon.api.Components
import org.hexworks.zircon.api.DrawSurfaces
import org.hexworks.zircon.api.component.renderer.ComponentDecorationRenderer
import org.hexworks.zircon.api.component.renderer.ComponentDecorationRenderer.Alignment.*
import org.hexworks.zircon.api.data.Size
import org.hexworks.zircon.convertCharacterTilesToString
import org.hexworks.zircon.internal.graphics.Renderable
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized

@RunWith(Parameterized::class)
class BoxDecorationRendererTest(
@Suppress("unused") private val testTitle: String, // used by Parameterized for display in IntelliJ/terminal
private val decorator: ComponentDecorationRenderer,
private val expected: String
) {
@Test
fun renderTest() {
val target = Components.panel()
.withTileset(CP437TilesetResources.rexPaint20x20())
.withDecorations(decorator)
.build()

val graphics = DrawSurfaces.tileGraphicsBuilder().withSize(Size.create(12, 4)).build()
(target as Renderable).render(graphics)
assertThat(graphics.convertCharacterTilesToString()).isEqualTo(expected.trimIndent())
}

companion object {
@Parameterized.Parameters(name = "{index}: {0}")
@JvmStatic
fun data() = listOf(
arrayOf("Default parameters", box(), """
┌──────────┐
│ │
│ │
└──────────┘
"""),
arrayOf("With title", box(title = "Foo"), """
┌┤Foo├─────┐
│ │
│ │
└──────────┘
"""),
arrayOf("With title, right-aligned", box(title = "Foo", titleAlignment = TOP_RIGHT), """
┌─────┤Foo├┐
│ │
│ │
└──────────┘
"""),
// Titlebar is even-sized width, but title is odd-sized, so we're off by half, rounding to the left.
arrayOf("With title, center-aligned, approx center", box(title = "Foo", titleAlignment = TOP_CENTER), """
┌──┤Foo├───┐
│ │
│ │
└──────────┘
"""),
arrayOf("With title, center-aligned, exact center", box(title = "Food", titleAlignment = TOP_CENTER), """
┌──┤Food├──┐
│ │
│ │
└──────────┘
"""),
arrayOf("With title, bottom left-aligned", box(title = "Foo", titleAlignment = BOTTOM_LEFT), """
┌──────────┐
│ │
│ │
└┤Foo├─────┘
"""),
arrayOf("With title, bottom right-aligned", box(title = "Foo", titleAlignment = BOTTOM_RIGHT), """
┌──────────┐
│ │
│ │
└─────┤Foo├┘
"""),
arrayOf("With title, bottom center-aligned", box(title = "Foo", titleAlignment = BOTTOM_CENTER), """
┌──────────┐
│ │
│ │
└──┤Foo├───┘
""")
)
}
}

0 comments on commit 8441af2

Please sign in to comment.