Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 43 additions & 5 deletions src/main/kotlin/com/fwdekker/randomness/array/ArrayDecorator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import com.intellij.util.xmlb.annotations.OptionTag
* @property maxCount The maximum number of elements to generate, inclusive.
* @property separatorEnabled Whether to separate elements using [separator].
* @property separator The string to place between generated elements.
* @property showIndices `true` if and only if array indices should be shown with each element.
* @property indicesFormat The format string for displaying array indices with elements.
* @property useTupleIndices `true` if and only if indices should be formatted as tuples for multi-dimensional arrays.
* @property affixDecorator The affixation to apply to the generated values.
*/
data class ArrayDecorator(
Expand All @@ -23,6 +26,9 @@ data class ArrayDecorator(
var maxCount: Int = DEFAULT_MAX_COUNT,
var separatorEnabled: Boolean = DEFAULT_SEPARATOR_ENABLED,
var separator: String = DEFAULT_SEPARATOR,
var showIndices: Boolean = DEFAULT_SHOW_INDICES,
var indicesFormat: String = DEFAULT_INDICES_FORMAT,
var useTupleIndices: Boolean = DEFAULT_USE_TUPLE_INDICES,
@OptionTag val affixDecorator: AffixDecorator = DEFAULT_AFFIX_DECORATOR,
) : DecoratorScheme() {
override val name = Bundle("array.title")
Expand All @@ -36,11 +42,23 @@ data class ArrayDecorator(
val parts = generator(partsPerString.sum())

return partsPerString
.fold(Pair(parts, emptyList<String>())) { (remainingParts, createdStrings), nextPartCount ->
val nextString =
remainingParts
.take(nextPartCount)
.joinToString(if (separatorEnabled) separator.replace("\\n", "\n") else "")
.foldIndexed(Pair(parts, emptyList<String>())) { arrayIndex, (remainingParts, createdStrings), nextPartCount ->
val nextParts = remainingParts.take(nextPartCount)
val formattedParts = if (showIndices) {
nextParts.mapIndexed { elementIndex, value ->
val indexStr = if (useTupleIndices) {
// Format as tuple for multi-dimensional arrays
"($arrayIndex,$elementIndex)"
} else {
elementIndex.toString()
}
indicesFormat.replace("{index}", indexStr).replace("{value}", value)
}
} else {
nextParts
}

val nextString = formattedParts.joinToString(if (separatorEnabled) separator.replace("\\n", "\n") else "")

Pair(remainingParts.drop(nextPartCount), createdStrings + nextString)
}
Expand Down Expand Up @@ -94,6 +112,26 @@ data class ArrayDecorator(
* The default value of the [separator] field.
*/
const val DEFAULT_SEPARATOR = ", "

/**
* The default value of the [showIndices] field.
*/
const val DEFAULT_SHOW_INDICES = false

/**
* The preset values for the [indicesFormat] field.
*/
val PRESET_INDICES_FORMATS = listOf("{index}: {value}", "{index}={value}", "\"{index}\": {value}")

/**
* The default value of the [indicesFormat] field.
*/
const val DEFAULT_INDICES_FORMAT = "{index}: {value}"

/**
* The default value of the [useTupleIndices] field.
*/
const val DEFAULT_USE_TUPLE_INDICES = false

/**
* The preset values for the [affixDecorator] descriptor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.fwdekker.randomness.SchemeEditor
import com.fwdekker.randomness.affix.AffixDecoratorEditor
import com.fwdekker.randomness.array.ArrayDecorator.Companion.MIN_MIN_COUNT
import com.fwdekker.randomness.array.ArrayDecorator.Companion.PRESET_AFFIX_DECORATOR_DESCRIPTORS
import com.fwdekker.randomness.array.ArrayDecorator.Companion.PRESET_INDICES_FORMATS
import com.fwdekker.randomness.array.ArrayDecorator.Companion.PRESET_SEPARATORS
import com.fwdekker.randomness.ui.JIntSpinner
import com.fwdekker.randomness.ui.UIConstants
Expand Down Expand Up @@ -91,6 +92,32 @@ class ArrayDecoratorEditor(
.withName("arraySeparator")
.bindCurrentText(scheme::separator)
}

row {
lateinit var showIndicesCheckBox: JCheckBox

checkBox(Bundle("array.ui.show_indices.option"))
.withName("arrayShowIndices")
.bindSelected(scheme::showIndices)
.also { showIndicesCheckBox = it.component }

comboBox(PRESET_INDICES_FORMATS)
.enabledIf(isEnabled.and(showIndicesCheckBox.selected))
.isEditable(true)
.withName("arrayIndicesFormat")
.bindCurrentText(scheme::indicesFormat)
}

row {
checkBox(Bundle("array.ui.use_tuple_indices.option"))
.withName("arrayUseTupleIndices")
.bindSelected(scheme::useTupleIndices)
.enabledIf(isEnabled.and(frame.checkBox("arrayShowIndices").selected))
}.enabledIf(isEnabled)

row {
comment(Bundle("array.ui.show_indices.comment"))
}.enabledIf(isEnabled)

row {
AffixDecoratorEditor(
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/randomness.properties
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ array.ui.enabled=&Enabled
array.ui.min_count_option=Min c&ount:
array.ui.max_count_option=Max co&unt:
array.ui.separator.option=Separator:
array.ui.show_indices.option=Show &indices:
array.ui.show_indices.comment=Use {index} for the array index and {value} for the element value.
array.ui.use_tuple_indices.option=Use &tuple indices (x,y):
datetime.error.min_datetime_above_max=Minimum date-time should be less than or equal to maximum date-time.
datetime.title=Date-Time
datetime.ui.pattern_comment=Escape characters by enclosing them in single quotes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,98 @@ object ArrayDecoratorEditorTest : FunSpec({
}
}
}

context("indices") {
context("embedded") {
beforeNonContainer {
frame.cleanUp()
editor = runEdt { ArrayDecoratorEditor(scheme, embedded = true) }
frame = showInFrame(editor.rootComponent)
}


test("disables indices format if checkbox is disabled") {
runEdt { frame.checkBox("arrayShowIndices").target().isSelected = false }

frame.comboBox("arrayIndicesFormat").requireDisabled()
}

test("enables indices format if checkbox is enabled") {
runEdt { frame.checkBox("arrayShowIndices").target().isSelected = true }

frame.comboBox("arrayIndicesFormat").requireEnabled()
}

test("disables tuple indices checkbox if show indices checkbox is disabled") {
runEdt { frame.checkBox("arrayShowIndices").target().isSelected = false }

frame.checkBox("arrayUseTupleIndices").requireDisabled()
}

test("enables tuple indices checkbox if show indices checkbox is enabled") {
runEdt { frame.checkBox("arrayShowIndices").target().isSelected = true }

frame.checkBox("arrayUseTupleIndices").requireEnabled()
}
}

context("not embedded") {
test("disables indices format if panel is disabled and checkbox is disabled") {
runEdt { frame.checkBox("arrayShowIndices").target().isSelected = false }

frame.comboBox("arrayIndicesFormat").requireDisabled()
}

test("disables indices format if panel is disabled and checkbox is enabled") {
runEdt { frame.checkBox("arrayEnabled").target().isSelected = false }
runEdt { frame.checkBox("arrayShowIndices").target().isSelected = true }

frame.comboBox("arrayIndicesFormat").requireDisabled()
}

test("disables indices format if panel is enabled and checkbox is disabled") {
runEdt { frame.checkBox("arrayEnabled").target().isSelected = true }
runEdt { frame.checkBox("arrayShowIndices").target().isSelected = false }

frame.comboBox("arrayIndicesFormat").requireDisabled()
}

test("enables indices format if panel is enabled and checkbox is enabled") {
runEdt { frame.checkBox("arrayEnabled").target().isSelected = true }
runEdt { frame.checkBox("arrayShowIndices").target().isSelected = true }

frame.comboBox("arrayIndicesFormat").requireEnabled()
}

test("disables tuple indices checkbox if panel and show indices are both disabled") {
runEdt { frame.checkBox("arrayEnabled").target().isSelected = false }
runEdt { frame.checkBox("arrayShowIndices").target().isSelected = false }

frame.checkBox("arrayUseTupleIndices").requireDisabled()
}

test("disables tuple indices checkbox if panel is disabled but show indices is enabled") {
runEdt { frame.checkBox("arrayEnabled").target().isSelected = false }
runEdt { frame.checkBox("arrayShowIndices").target().isSelected = true }

frame.checkBox("arrayUseTupleIndices").requireDisabled()
}

test("disables tuple indices checkbox if panel is enabled but show indices is disabled") {
runEdt { frame.checkBox("arrayEnabled").target().isSelected = true }
runEdt { frame.checkBox("arrayShowIndices").target().isSelected = false }

frame.checkBox("arrayUseTupleIndices").requireDisabled()
}

test("enables tuple indices checkbox if panel and show indices are both enabled") {
runEdt { frame.checkBox("arrayEnabled").target().isSelected = true }
runEdt { frame.checkBox("arrayShowIndices").target().isSelected = true }

frame.checkBox("arrayUseTupleIndices").requireEnabled()
}
}
}
}


Expand Down Expand Up @@ -207,6 +299,27 @@ object ArrayDecoratorEditorTest : FunSpec({
" - ",
)
},
"showIndices" to {
row(
frame.checkBox("arrayShowIndices").isSelectedProp(),
editor.scheme::showIndices.prop(),
true,
)
},
"indicesFormat" to {
row(
frame.comboBox("arrayIndicesFormat").textProp(),
editor.scheme::indicesFormat.prop(),
"\"{index}\": {value}",
)
},
"useTupleIndices" to {
row(
frame.checkBox("arrayUseTupleIndices").isSelectedProp(),
editor.scheme::useTupleIndices.prop(),
true,
)
},
"affixDecorator" to {
row(
frame.comboBox("arrayAffixDescriptor").textProp(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,31 @@ object ArrayDecoratorTest : FunSpec({
ArrayDecorator(enabled = true, affixDecorator = AffixDecorator(enabled = true, "(@)")),
"({i0}, {i1}, {i2})",
),
"shows indices with default format" to
row(
ArrayDecorator(enabled = true, showIndices = true, indicesFormat = "{index}: {value}"),
"[0: {i0}, 1: {i1}, 2: {i2}]",
),
"shows indices with custom format" to
row(
ArrayDecorator(enabled = true, showIndices = true, indicesFormat = "{index}={value}"),
"[0={i0}, 1={i1}, 2={i2}]",
),
"shows indices with json-like format" to
row(
ArrayDecorator(enabled = true, showIndices = true, indicesFormat = "\"{index}\": {value}"),
"[\"0\": {i0}, \"1\": {i1}, \"2\": {i2}]",
),
"doesn't show indices when disabled" to
row(
ArrayDecorator(enabled = true, showIndices = false, indicesFormat = "{index}: {value}"),
"[{i0}, {i1}, {i2}]",
),
"shows tuple indices when enabled" to
row(
ArrayDecorator(enabled = true, showIndices = true, useTupleIndices = true, indicesFormat = "{index}: {value}"),
"[(0,0): {i0}, (0,1): {i1}, (0,2): {i2}]",
),
)
) { (scheme, output) ->
scheme.generator = { count -> List(count) { "{i$it}" } }
Expand Down Expand Up @@ -90,6 +115,22 @@ object ArrayDecoratorTest : FunSpec({

scheme.generateStrings(count = 2) shouldBe listOf("[{i0}, {i1}, {i2}]", "[{i3}, {i4}, {i5}]")
}

test("correctly applies indices to multiple array outputs") {
val scheme = ArrayDecorator(enabled = true, showIndices = true, indicesFormat = "{index}: {value}")
var partIdx = 0
scheme.generator = { count -> List(count) { "{i${partIdx++}}" } }

scheme.generateStrings(count = 2) shouldBe listOf("[0: {i0}, 1: {i1}, 2: {i2}]", "[0: {i3}, 1: {i4}, 2: {i5}]")
}

test("correctly applies tuple indices to multiple array outputs") {
val scheme = ArrayDecorator(enabled = true, showIndices = true, useTupleIndices = true, indicesFormat = "{index}: {value}")
var partIdx = 0
scheme.generator = { count -> List(count) { "{i${partIdx++}}" } }

scheme.generateStrings(count = 2) shouldBe listOf("[(0,0): {i0}, (0,1): {i1}, (0,2): {i2}]", "[(1,0): {i3}, (1,1): {i4}, (1,2): {i5}]")
}
}

context("doValidate") {
Expand Down
Loading