From e461cbcd20f961dcb989c4babade1cf727ef7dfe Mon Sep 17 00:00:00 2001 From: "Florine W. Dekker" Date: Sun, 22 Oct 2023 22:36:53 +0200 Subject: [PATCH] Always use square icon for `Template`s Fixes #484. --- .../kotlin/com/fwdekker/randomness/Icons.kt | 23 ++--- .../fwdekker/randomness/template/Template.kt | 2 +- .../com/fwdekker/randomness/IconsTest.kt | 90 ++++++++++++------- .../template/TemplateActionTests.kt | 4 +- .../randomness/template/TemplateTest.kt | 17 ++-- 5 files changed, 84 insertions(+), 52 deletions(-) diff --git a/src/main/kotlin/com/fwdekker/randomness/Icons.kt b/src/main/kotlin/com/fwdekker/randomness/Icons.kt index e654ce99a..afddb9ef0 100644 --- a/src/main/kotlin/com/fwdekker/randomness/Icons.kt +++ b/src/main/kotlin/com/fwdekker/randomness/Icons.kt @@ -85,17 +85,6 @@ data class TypeIcon(val base: Icon, val text: String, val colors: List) : } - /** - * Returns an icon that describes both this icon's type and [other]'s type. - */ - fun combineWith(other: TypeIcon) = - TypeIcon( - Icons.TEMPLATE, - if (this.text == other.text) this.text else "", - this.colors + other.colors - ) - - /** * Paints the colored text icon. * @@ -133,6 +122,18 @@ data class TypeIcon(val base: Icon, val text: String, val colors: List) : * The scale of the text inside the icon relative to the icon's size. */ const val FONT_SIZE = 12f / 32f + + + /** + * Returns a single icon that describes all [icons], or `null` if [icons] is empty. + */ + fun combine(icons: Collection): TypeIcon? = + if (icons.isEmpty()) null + else TypeIcon( + Icons.TEMPLATE, + if (icons.map { it.text }.toSet().size == 1) icons.first().text else "", + icons.flatMap { it.colors } + ) } } diff --git a/src/main/kotlin/com/fwdekker/randomness/template/Template.kt b/src/main/kotlin/com/fwdekker/randomness/template/Template.kt index 4bf926f5a..414f7b898 100644 --- a/src/main/kotlin/com/fwdekker/randomness/template/Template.kt +++ b/src/main/kotlin/com/fwdekker/randomness/template/Template.kt @@ -42,7 +42,7 @@ data class Template( val arrayDecorator: ArrayDecorator = DEFAULT_ARRAY_DECORATOR, ) : Scheme() { override val typeIcon - get() = schemes.mapNotNull { it.typeIcon }.reduceOrNull { acc, icon -> acc.combineWith(icon) } ?: DEFAULT_ICON + get() = TypeIcon.combine(schemes.mapNotNull { it.typeIcon }) ?: DEFAULT_ICON override val decorators get() = listOf(arrayDecorator) /** diff --git a/src/test/kotlin/com/fwdekker/randomness/IconsTest.kt b/src/test/kotlin/com/fwdekker/randomness/IconsTest.kt index 2d1e4cca2..f6ab4ea81 100644 --- a/src/test/kotlin/com/fwdekker/randomness/IconsTest.kt +++ b/src/test/kotlin/com/fwdekker/randomness/IconsTest.kt @@ -7,6 +7,7 @@ import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.collections.beEmpty import io.kotest.matchers.collections.shouldContainExactly +import io.kotest.matchers.nulls.beNull import io.kotest.matchers.should import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNot @@ -33,37 +34,6 @@ object TypeIconTest : FunSpec({ } - context("combineWith") { - test("returns a template TypeIcon") { - val icon1 = TypeIcon(PlainIcon(), "text1", listOf(Color.GREEN)) - val icon2 = TypeIcon(PlainIcon(), "text2", listOf(Color.RED)) - - icon1.combineWith(icon2).base shouldBe Icons.TEMPLATE - } - - test("retains the text if it is the same for both icons") { - val icon1 = TypeIcon(PlainIcon(), "text", listOf(Color.PINK)) - val icon2 = TypeIcon(PlainIcon(), "text", listOf(Color.CYAN)) - - icon1.combineWith(icon2).text shouldBe "text" - } - - test("removes the text if it is different for the icons") { - val icon1 = TypeIcon(PlainIcon(), "text1", listOf(Color.GRAY)) - val icon2 = TypeIcon(PlainIcon(), "text2", listOf(Color.ORANGE)) - - icon1.combineWith(icon2).text shouldBe "" - } - - test("appends the colors of the combined icons") { - val icon1 = TypeIcon(PlainIcon(), "text1", listOf(Color.BLUE, Color.WHITE)) - val icon2 = TypeIcon(PlainIcon(), "text2", listOf(Color.RED, Color.PINK)) - - icon1.combineWith(icon2).colors shouldContainExactly listOf(Color.BLUE, Color.WHITE, Color.RED, Color.PINK) - } - } - - context("paintIcon") { tags(Tags.SWING) @@ -98,6 +68,64 @@ object TypeIconTest : FunSpec({ image.getRGB(0, 0, 32, 32, null, 0, 32).filter { it != 0 } shouldNot beEmpty() } } + + + context("combine") { + test("returns `null` if no icons are given to combine") { + TypeIcon.combine(emptyList()) should beNull() + } + + test("returns a template icon for a single icon") { + val icons = listOf(TypeIcon(PlainIcon(), "text", listOf(Color.LIGHT_GRAY))) + + TypeIcon.combine(icons)!!.base shouldBe Icons.TEMPLATE + } + + test("returns a template icon for multiple icons") { + val icons = + listOf( + TypeIcon(PlainIcon(), "text1", listOf(Color.GREEN)), + TypeIcon(PlainIcon(), "text2", listOf(Color.RED)), + TypeIcon(PlainIcon(), "text3", listOf(Color.MAGENTA)), + ) + + TypeIcon.combine(icons)!!.base shouldBe Icons.TEMPLATE + } + + test("retains the text if it is the same for all icons") { + val icons = + listOf( + TypeIcon(PlainIcon(), "text", listOf(Color.PINK)), + TypeIcon(PlainIcon(), "text", listOf(Color.CYAN)), + TypeIcon(PlainIcon(), "text", listOf(Color.GREEN)), + ) + + TypeIcon.combine(icons)!!.text shouldBe "text" + } + + test("removes the text if it is not the same for all icons") { + val icons = + listOf( + TypeIcon(PlainIcon(), "text1", listOf(Color.GRAY)), + TypeIcon(PlainIcon(), "text2", listOf(Color.ORANGE)), + TypeIcon(PlainIcon(), "text2", listOf(Color.BLUE)), + ) + + TypeIcon.combine(icons)!!.text shouldBe "" + } + + test("appends the colors of the combined icons") { + val icons = + listOf( + TypeIcon(PlainIcon(), "text1", listOf(Color.BLUE, Color.WHITE)), + TypeIcon(PlainIcon(), "text2", listOf(Color.RED)), + TypeIcon(PlainIcon(), "text3", listOf(Color.PINK, Color.BLACK, Color.BLUE)), + ) + + TypeIcon.combine(icons)!!.colors shouldContainExactly + listOf(Color.BLUE, Color.WHITE, Color.RED, Color.PINK, Color.BLACK, Color.BLUE) + } + } }) /** diff --git a/src/test/kotlin/com/fwdekker/randomness/template/TemplateActionTests.kt b/src/test/kotlin/com/fwdekker/randomness/template/TemplateActionTests.kt index 2ccc69014..db429b889 100644 --- a/src/test/kotlin/com/fwdekker/randomness/template/TemplateActionTests.kt +++ b/src/test/kotlin/com/fwdekker/randomness/template/TemplateActionTests.kt @@ -185,11 +185,11 @@ object TemplateSettingsActionTest : FunSpec({ } test("uses the template's icon if the template is not null") { - val icon = TypeIcon(Icons.SCHEME, "war", listOf(Color.GREEN)) + val icon = TypeIcon(Icons.SCHEME, "wax", listOf(Color.GREEN)) val template = Template("subject", mutableListOf(DummyScheme().also { it.typeIcon = icon })) val action = TemplateSettingsAction(template) - (action.templatePresentation.icon as OverlayedIcon).base shouldBe icon + (action.templatePresentation.icon as OverlayedIcon).base shouldBe template.typeIcon } } } diff --git a/src/test/kotlin/com/fwdekker/randomness/template/TemplateTest.kt b/src/test/kotlin/com/fwdekker/randomness/template/TemplateTest.kt index ffebfb1d6..6fb831656 100644 --- a/src/test/kotlin/com/fwdekker/randomness/template/TemplateTest.kt +++ b/src/test/kotlin/com/fwdekker/randomness/template/TemplateTest.kt @@ -2,6 +2,7 @@ package com.fwdekker.randomness.template import com.fwdekker.randomness.CapitalizationMode import com.fwdekker.randomness.DataGenerationException +import com.fwdekker.randomness.Icons import com.fwdekker.randomness.Settings import com.fwdekker.randomness.array.ArrayDecorator import com.fwdekker.randomness.integer.IntegerScheme @@ -30,11 +31,10 @@ object TemplateTest : FunSpec({ context("typeIcon") { - test("returns the single scheme's icon if that scheme has an icon") { - val scheme = IntegerScheme() - val template = Template(schemes = mutableListOf(scheme)) + test("returns the default icon if the template contains no schemes") { + val template = Template() - template.typeIcon shouldBe scheme.typeIcon + template.typeIcon shouldBe Template.DEFAULT_ICON } test("returns the default icon if the single scheme has no icon") { @@ -44,10 +44,13 @@ object TemplateTest : FunSpec({ template.typeIcon shouldBe Template.DEFAULT_ICON } - test("returns the default icon if no scheme is present") { - val template = Template() + test("returns a template version of the single scheme's TypeIcon") { + val scheme = IntegerScheme() + val template = Template(schemes = mutableListOf(scheme)) - template.typeIcon shouldBe Template.DEFAULT_ICON + template.typeIcon.base shouldBe Icons.TEMPLATE + template.typeIcon.text shouldBe scheme.typeIcon.text + template.typeIcon.colors shouldBe scheme.typeIcon.colors } test("returns the scheme's combined icon if multiple are present") {