Skip to content

Commit 1fb0738

Browse files
committed
fix collection setting imgui logic
1 parent af9b1c8 commit 1fb0738

File tree

5 files changed

+52
-164
lines changed

5 files changed

+52
-164
lines changed

src/main/kotlin/com/lambda/config/UserAutomationConfig.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,6 @@ class UserAutomationConfig(override val name: String) : AutomationConfig(name, U
3838
}
3939

4040
private fun Module.removeLink() {
41-
(automationConfig as UserAutomationConfig).linkedModules.value -= name
41+
(automationConfig as? UserAutomationConfig)?.linkedModules?.value -= name
4242
}
4343
}

src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -21,60 +21,19 @@ import com.google.gson.JsonElement
2121
import com.google.gson.reflect.TypeToken
2222
import com.lambda.Lambda.gson
2323
import com.lambda.config.Setting
24-
import com.lambda.config.serializer.BlockCodec
2524
import com.lambda.gui.dsl.ImGuiBuilder
26-
import com.lambda.util.StringUtils.levenshteinDistance
27-
import imgui.ImGuiListClipper
28-
import imgui.flag.ImGuiChildFlags
29-
import imgui.flag.ImGuiSelectableFlags.DontClosePopups
3025
import net.minecraft.block.Block
3126

3227
class BlockCollectionSetting(
33-
private val immutableCollection: Collection<Block>,
28+
immutableCollection: Collection<Block>,
3429
defaultValue: MutableCollection<Block>,
3530
) : CollectionSetting<Block>(
3631
defaultValue,
3732
immutableCollection,
3833
TypeToken.getParameterized(Collection::class.java, Block::class.java).type
3934
) {
40-
private var searchFilter = ""
41-
4235
context(setting: Setting<*, MutableCollection<Block>>)
43-
override fun ImGuiBuilder.buildLayout() {
44-
val text = if (value.size == 1) "block" else "blocks"
45-
46-
combo("##${setting.name}", "${setting.name}: ${value.size} $text") {
47-
inputText("##${setting.name}-SearchBox", ::searchFilter)
48-
49-
child(
50-
strId = "##${setting.name}-ComboOptionsChild",
51-
childFlags = ImGuiChildFlags.AutoResizeY or ImGuiChildFlags.AlwaysAutoResize,
52-
) {
53-
val list = immutableCollection
54-
.filter { searchFilter == "" || searchFilter.levenshteinDistance(BlockCodec.stringify(it)) < 3 }
55-
56-
ImGuiListClipper.forEach { // not actually iterating
57-
it.begin(list.size)
58-
59-
while (it.step()) {
60-
for (i in it.displayStart..it.displayEnd) {
61-
val v = list.getOrNull(i) ?: continue
62-
val selected = value.contains(v)
63-
64-
selectable(
65-
label = BlockCodec.stringify(v),
66-
selected = selected,
67-
flags = DontClosePopups
68-
) {
69-
if (selected) value.remove(v)
70-
else value.add(v)
71-
}
72-
}
73-
}
74-
}
75-
}
76-
}
77-
}
36+
override fun ImGuiBuilder.buildLayout() = buildComboBox("block")
7837

7938
context(setting: Setting<*, MutableCollection<Block>>)
8039
override fun toJson(): JsonElement = gson.toJsonTree(value, type)

src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSetting.kt

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,7 @@ import com.google.gson.reflect.TypeToken
2222
import com.lambda.Lambda.gson
2323
import com.lambda.config.Setting
2424
import com.lambda.gui.dsl.ImGuiBuilder
25-
import com.lambda.util.StringUtils.levenshteinDistance
2625
import com.lambda.util.reflections.className
27-
import imgui.ImGuiListClipper
28-
import imgui.flag.ImGuiChildFlags
29-
import imgui.flag.ImGuiSelectableFlags.DontClosePopups
3026

3127
/**
3228
* @see [com.lambda.config.settings.collections.CollectionSetting]
@@ -40,44 +36,8 @@ class ClassCollectionSetting<T : Any>(
4036
immutableCollection,
4137
TypeToken.getParameterized(Collection::class.java, Any::class.java).type
4238
) {
43-
private var searchFilter = ""
44-
4539
context(setting: Setting<*, MutableCollection<T>>)
46-
override fun ImGuiBuilder.buildLayout() {
47-
val text = if (value.size == 1) "item" else "items"
48-
49-
combo("##${setting.name}", "${setting.name}: ${value.size} $text") {
50-
inputText("##${setting.name}-SearchBox", ::searchFilter)
51-
52-
child(
53-
strId = "##${setting.name}-ComboOptionsChild",
54-
childFlags = ImGuiChildFlags.AutoResizeY or ImGuiChildFlags.AlwaysAutoResize,
55-
) {
56-
val list = immutableCollection
57-
.filter { searchFilter == "" || searchFilter.levenshteinDistance(it.className) < 3 }
58-
59-
ImGuiListClipper.forEach { // not actually iterating
60-
it.begin(list.size)
61-
62-
while (it.step()) {
63-
for (i in it.displayStart..it.displayEnd) {
64-
val v = list.getOrNull(i) ?: continue
65-
val selected = value.contains(v)
66-
67-
selectable(
68-
label = v.className,
69-
selected = selected,
70-
flags = DontClosePopups
71-
) {
72-
if (selected) value.remove(v)
73-
else value.add(v)
74-
}
75-
}
76-
}
77-
}
78-
}
79-
}
80-
}
40+
override fun ImGuiBuilder.buildLayout() = buildComboBox("item")
8141

8242
// When serializing the list to json we do not want to serialize the elements' classes, but their stringified representation.
8343
// If we do serialize the classes we'll run into missing type adapters errors by Gson.

src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ import com.lambda.config.SettingEditorDsl
2626
import com.lambda.config.SettingGroupEditor
2727
import com.lambda.context.SafeContext
2828
import com.lambda.gui.dsl.ImGuiBuilder
29-
import com.lambda.util.StringUtils.levenshteinDistance
29+
import com.lambda.threading.runSafe
3030
import imgui.ImGuiListClipper
31+
import imgui.callback.ImListClipperCallback
3132
import imgui.flag.ImGuiChildFlags
3233
import imgui.flag.ImGuiSelectableFlags.DontClosePopups
3334
import java.lang.reflect.Type
@@ -58,41 +59,50 @@ open class CollectionSetting<R : Any>(
5859
val deselectListeners = mutableListOf<SafeContext.(R) -> Unit>()
5960

6061
context(setting: Setting<*, MutableCollection<R>>)
61-
override fun ImGuiBuilder.buildLayout() {
62-
val text = if (value.size == 1) "item" else "items"
63-
64-
combo("##${setting.name}", "${setting.name}: ${value.size} $text") {
65-
inputText("##${setting.name}-SearchBox", ::searchFilter)
66-
67-
child(
68-
strId = "##${setting.name}-ComboOptionsChild",
69-
childFlags = ImGuiChildFlags.AutoResizeY or ImGuiChildFlags.AlwaysAutoResize,
70-
) {
71-
val list = immutableCollection
72-
.filter { searchFilter == "" || searchFilter.levenshteinDistance(it.toString()) < 3 }
73-
74-
ImGuiListClipper.forEach { // not actually iterating
75-
it.begin(list.size)
76-
77-
while (it.step()) {
78-
for (i in it.displayStart..it.displayEnd) {
79-
val v = list.getOrNull(i) ?: continue
80-
val selected = value.contains(v)
81-
82-
selectable(
83-
label = v.toString(),
84-
selected = selected,
85-
flags = DontClosePopups
86-
) {
87-
if (selected) value.remove(v)
88-
else value.add(v)
89-
}
90-
}
91-
}
92-
}
93-
}
94-
}
95-
}
62+
override fun ImGuiBuilder.buildLayout() = buildComboBox("item")
63+
64+
context(setting: Setting<*, MutableCollection<R>>)
65+
fun ImGuiBuilder.buildComboBox(itemName: String) {
66+
val text = if (value.size == 1) itemName else "${itemName}s"
67+
68+
combo("##${setting.name}", "${setting.name}: ${value.size} $text") {
69+
inputText("##${setting.name}-SearchBox", ::searchFilter)
70+
71+
child(
72+
strId = "##${setting.name}-ComboOptionsChild",
73+
childFlags = ImGuiChildFlags.AutoResizeY or ImGuiChildFlags.AlwaysAutoResize,
74+
) {
75+
val list = immutableCollection
76+
.filter { item ->
77+
val q = searchFilter.trim()
78+
if (q.isEmpty()) true
79+
else item.toString().startsWith(q, ignoreCase = true)
80+
}
81+
82+
val listClipperCallback = object : ImListClipperCallback() {
83+
override fun accept(index: Int) {
84+
val v = list.getOrNull(index) ?: return
85+
val selected = value.contains(v)
86+
87+
selectable(
88+
label = v.toString(),
89+
selected = selected,
90+
flags = DontClosePopups
91+
) {
92+
if (selected) {
93+
value.remove(v)
94+
runSafe { deselectListeners.forEach { listener -> listener(v) } }
95+
} else {
96+
value.add(v)
97+
runSafe { selectListeners.forEach { listener -> listener(v) } }
98+
}
99+
}
100+
}
101+
}
102+
ImGuiListClipper.forEach(list.size, listClipperCallback)
103+
}
104+
}
105+
}
96106

97107
context(setting: Setting<*, MutableCollection<R>>)
98108
override fun toJson(): JsonElement =

src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -21,60 +21,19 @@ import com.google.gson.JsonElement
2121
import com.google.gson.reflect.TypeToken
2222
import com.lambda.Lambda.gson
2323
import com.lambda.config.Setting
24-
import com.lambda.config.serializer.ItemCodec
2524
import com.lambda.gui.dsl.ImGuiBuilder
26-
import com.lambda.util.StringUtils.levenshteinDistance
27-
import imgui.ImGuiListClipper
28-
import imgui.flag.ImGuiChildFlags
29-
import imgui.flag.ImGuiSelectableFlags.DontClosePopups
3025
import net.minecraft.item.Item
3126

3227
class ItemCollectionSetting(
33-
private val immutableCollection: Collection<Item>,
28+
immutableCollection: Collection<Item>,
3429
defaultValue: MutableCollection<Item>
3530
) : CollectionSetting<Item>(
3631
defaultValue,
3732
immutableCollection,
3833
TypeToken.getParameterized(Collection::class.java, Item::class.java).type
3934
) {
40-
private var searchFilter = ""
41-
4235
context(setting: Setting<*, MutableCollection<Item>>)
43-
override fun ImGuiBuilder.buildLayout() {
44-
val text = if (value.size == 1) "item" else "items"
45-
46-
combo("##${setting.name}", "${setting.name}: ${value.size} $text") {
47-
inputText("##${setting.name}-SearchBox", ::searchFilter)
48-
49-
child(
50-
strId = "##${setting.name}-ComboOptionsChild",
51-
childFlags = ImGuiChildFlags.AutoResizeY or ImGuiChildFlags.AlwaysAutoResize,
52-
) {
53-
val list = immutableCollection
54-
.filter { searchFilter == "" || searchFilter.levenshteinDistance(ItemCodec.stringify(it)) < 3 }
55-
56-
ImGuiListClipper.forEach { // not actually iterating
57-
it.begin(list.size)
58-
59-
while (it.step()) {
60-
for (i in it.displayStart..it.displayEnd) {
61-
val v = list.getOrNull(i) ?: continue
62-
val selected = value.contains(v)
63-
64-
selectable(
65-
label = ItemCodec.stringify(v),
66-
selected = selected,
67-
flags = DontClosePopups
68-
) {
69-
if (selected) value.remove(v)
70-
else value.add(v)
71-
}
72-
}
73-
}
74-
}
75-
}
76-
}
77-
}
36+
override fun ImGuiBuilder.buildLayout() = buildComboBox("item")
7837

7938
context(setting: Setting<*, MutableCollection<Item>>)
8039
override fun toJson(): JsonElement = gson.toJsonTree(value, type)

0 commit comments

Comments
 (0)