Skip to content

Commit 5887489

Browse files
committed
Add processed category interface
1 parent 845da23 commit 5887489

File tree

8 files changed

+131
-61
lines changed

8 files changed

+131
-61
lines changed

common/src/main/java/io/github/notenoughupdates/moulconfig/Config.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ public HorizontalAlign alignCategory(ProcessedCategory category, boolean isSelec
3838

3939
public String formatCategoryName(ProcessedCategory category, boolean isSelected) {
4040
if (isSelected) {
41-
return "§b§n" + category.name;
42-
} else if (category.parent == null) {
43-
return "§7" + category.name;
41+
return "§b§n" + category.getDisplayName();
42+
} else if (category.getParentCategoryId() == null) {
43+
return "§7" + category.getDisplayName();
4444
} else {
45-
return "§8" + category.name;
45+
return "§8" + category.getDisplayName();
4646
}
4747
}
4848

common/src/main/java/io/github/notenoughupdates/moulconfig/gui/MoulConfigEditor.java

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public class MoulConfigEditor<T extends Config> extends GuiElement {
6767
@Setter
6868
private SearchFunction searchFunction = GuiOptionEditor::fulfillsSearch;
6969

70-
private LinkedHashMap<String, ProcessedCategory> currentlyVisibleCategories;
70+
private LinkedHashMap<String, ? extends ProcessedCategory> currentlyVisibleCategories;
7171
private Set<ProcessedOption> currentlyVisibleOptions;
7272
private Map<String, Set<String>> childCategoryLookup = new HashMap<>();
7373
private List<ProcessedOption> allOptions = new ArrayList<>();
@@ -76,10 +76,10 @@ public MoulConfigEditor(MoulConfigProcessor<T> processedConfig) {
7676
processedConfig.requireFinalized();
7777
this.openedMillis = System.currentTimeMillis();
7878
this.processedConfig = processedConfig;
79-
for (Map.Entry<String, ProcessedCategory> category : processedConfig.getAllCategories().entrySet()) {
80-
allOptions.addAll(category.getValue().options);
81-
if (category.getValue().parent != null) {
82-
childCategoryLookup.computeIfAbsent(category.getValue().parent, ignored -> new HashSet<>())
79+
for (Map.Entry<String, ? extends ProcessedCategory> category : processedConfig.getAllCategories().entrySet()) {
80+
allOptions.addAll(category.getValue().getOptions());
81+
if (category.getValue().getParentCategoryId() != null) {
82+
childCategoryLookup.computeIfAbsent(category.getValue().getParentCategoryId(), ignored -> new HashSet<>())
8383
.add(category.getKey());
8484
}
8585
}
@@ -91,7 +91,7 @@ public MoulConfigEditor(MoulConfigProcessor<T> processedConfig) {
9191
}
9292

9393
private List<ProcessedOption> getOptionsInCategory(ProcessedCategory cat) {
94-
List<ProcessedOption> options = new ArrayList<>(cat.options);
94+
List<ProcessedOption> options = new ArrayList<>(cat.getOptions());
9595
options.removeIf(it -> !currentlyVisibleOptions.contains(it));
9696
return options;
9797
}
@@ -107,7 +107,7 @@ public boolean scrollOptionIntoView(ProcessedOption searchedOption, int timeToRe
107107
// Recursively expand accordions this option is in
108108
var accordionP = searchedOption;
109109
while (accordionP.getAccordionId() >= 0) {
110-
accordionP = processedCategory.accordionAnchors.get(accordionP.getAccordionId());
110+
accordionP = processedCategory.getAccordionAnchors().get(accordionP.getAccordionId());
111111
((GuiOptionEditorAccordion) accordionP.getEditor()).setToggled(true);
112112
}
113113

@@ -169,7 +169,7 @@ private void propagateSearchinessForAccordions(Set<ProcessedOption> options, Set
169169

170170
for (ProcessedOption option : lastRound) {
171171
if (option.getAccordionId() >= 0 && upwards) {
172-
for (ProcessedOption accordion : option.getCategory().options) {
172+
for (ProcessedOption accordion : option.getCategory().getOptions()) {
173173
if (accordion == option) continue;
174174
if (!(accordion.getEditor() instanceof GuiOptionEditorAccordion)) continue;
175175
if (((GuiOptionEditorAccordion) accordion.getEditor()).getAccordionId() == option.getAccordionId()) {
@@ -179,7 +179,7 @@ private void propagateSearchinessForAccordions(Set<ProcessedOption> options, Set
179179
}
180180
if (option.getEditor() instanceof GuiOptionEditorAccordion && !upwards) {
181181
int parentId = ((GuiOptionEditorAccordion) option.getEditor()).getAccordionId();
182-
for (ProcessedOption potentialChild : option.getCategory().options) {
182+
for (ProcessedOption potentialChild : option.getCategory().getOptions()) {
183183
if (potentialChild.getAccordionId() == parentId) {
184184
nextRound.add(potentialChild);
185185
}
@@ -201,7 +201,7 @@ public void updateSearchResults(boolean recalculateOptionUniverse) {
201201
if (recalculateOptionUniverse) {
202202
allOptions.clear();
203203
for (ProcessedCategory category : processedConfig.getAllCategories().values()) {
204-
allOptions.addAll(category.options);
204+
allOptions.addAll(category.getOptions());
205205
}
206206
}
207207
String toSearch = searchFieldContent.get().trim().toLowerCase(Locale.ROOT);
@@ -214,14 +214,15 @@ public void updateSearchResults(boolean recalculateOptionUniverse) {
214214
HashSet<ProcessedCategory> directlyMatchedCategories = new HashSet<>(processedConfig.getAllCategories().values());
215215
if (!processedConfig.getConfigObject().shouldSearchCategoryNames()) directlyMatchedCategories.clear();
216216
for (String word : toSearch.split(" +")) {
217-
directlyMatchedCategories.removeIf(it -> ContextAware.wrapErrorWithContext(it.reflectField,
218-
() -> !(it.name.toLowerCase(Locale.ROOT).contains(word) || it.desc.toLowerCase(Locale.ROOT).contains(word))));
217+
directlyMatchedCategories.removeIf(it -> ContextAware.wrapErrorWithContext(it,
218+
() -> !(it.getDisplayName().toLowerCase(Locale.ROOT).contains(word)
219+
|| it.getDescription().toLowerCase(Locale.ROOT).contains(word))));
219220
}
220221

221222
Set<ProcessedOption> matchingOptionsAndDependencies = new HashSet<>();
222223

223224
var childCategoriesOfDirectlyMatched = directlyMatchedCategories.stream()
224-
.flatMap(it -> childCategoryLookup.getOrDefault(it.name, Collections.emptySet()).stream())
225+
.flatMap(it -> childCategoryLookup.getOrDefault(it.getIdentifier(), Collections.emptySet()).stream())
225226
.map(processedConfig.getAllCategories()::get)
226227
.filter(Objects::nonNull)
227228
.collect(Collectors.toList());
@@ -230,18 +231,21 @@ public void updateSearchResults(boolean recalculateOptionUniverse) {
230231
// No search propagation needed if category is matched.
231232
// Add them directly to the final visible option set.
232233
for (ProcessedCategory directCategory : directlyMatchedCategories) {
233-
matchingOptionsAndDependencies.addAll(directCategory.options);
234-
directCategory.options.forEach(matchingOptions::remove);
234+
matchingOptionsAndDependencies.addAll(directCategory.getOptions());
235+
directCategory.getOptions().forEach(matchingOptions::remove);
235236
}
236237

237238
propagateSearchinessForAccordions(matchingOptionsAndDependencies, matchingOptions, true);
238239
propagateSearchinessForAccordions(matchingOptionsAndDependencies, matchingOptions, false);
239240

240241
currentlyVisibleOptions = matchingOptionsAndDependencies;
241242

242-
Set<ProcessedCategory> visibleCategories = matchingOptionsAndDependencies.stream().map(it -> it.getCategory()).collect(Collectors.toSet());
243+
Set<ProcessedCategory> visibleCategories = matchingOptionsAndDependencies
244+
.stream()
245+
.map(ProcessedOption::getCategory).collect(Collectors.toSet());
243246
Set<ProcessedCategory> parentCategories = visibleCategories.stream()
244-
.filter(it -> it.parent != null).map(it -> processedConfig.getAllCategories().get(it.parent))
247+
.filter(it -> it.getParentCategoryId() != null)
248+
.map(it -> processedConfig.getAllCategories().get(it.getParentCategoryId()))
245249
.filter(Objects::nonNull).collect(Collectors.toSet());
246250
visibleCategories.addAll(parentCategories);
247251
LinkedHashMap<String, ProcessedCategory> matchingCategories = new LinkedHashMap<>(processedConfig.getAllCategories());
@@ -254,21 +258,21 @@ public void updateSearchResults(boolean recalculateOptionUniverse) {
254258
}
255259

256260
public LinkedHashMap<String, ProcessedCategory> getCurrentlyVisibleCategories() {
257-
var newHashes = new LinkedHashMap<>(currentlyVisibleCategories);
261+
var newHashes = new LinkedHashMap<String, ProcessedCategory>(currentlyVisibleCategories);
258262
newHashes.entrySet().removeIf(it -> {
259-
if (it.getValue().parent == null) return false;
263+
if (it.getValue().getParentCategoryId() == null) return false;
260264
if (!showSubcategories) return true;
261-
if (it.getValue().parent.equals(getSelectedCategory())) return false;
265+
if (it.getValue().getParentCategoryId().equals(getSelectedCategory())) return false;
262266
var processedCategory = currentlyVisibleCategories.get(getSelectedCategory());
263267
if (processedCategory == null) return true;
264268
//noinspection RedundantIfStatement
265-
if (it.getValue().parent.equals(processedCategory.parent)) return false;
269+
if (it.getValue().getParentCategoryId().equals(processedCategory.getParentCategoryId())) return false;
266270
return true;
267271
});
268272
return newHashes;
269273
}
270274

271-
public LinkedHashMap<String, ProcessedCategory> getCurrentlySearchedCategories() {
275+
public LinkedHashMap<String, ? extends ProcessedCategory> getCurrentlySearchedCategories() {
272276
return currentlyVisibleCategories;
273277
}
274278

@@ -378,7 +382,7 @@ public void render() {
378382
var catName = processedConfig.getConfigObject().formatCategoryName(entry.getValue(), isSelected);
379383
var align = processedConfig.getConfigObject().alignCategory(entry.getValue(), isSelected);
380384
var textLength = ifr.getStringWidth(catName);
381-
var isIndented = childCategories != null || entry.getValue().parent != null;
385+
var isIndented = childCategories != null || entry.getValue().getParentCategoryId() != null;
382386
if (textLength > ((isIndented) ? 90 : 100)) {
383387
context.drawStringCenteredScaledMaxWidth(catName,
384388
ifr, x + 75 + (isIndented ? 5 : 0), y + 70 + catY, false, (isIndented ? 90 : 100), -1
@@ -477,7 +481,7 @@ public void render() {
477481
ProcessedCategory cat = currentConfigEditing.get(getSelectedCategory());
478482

479483
context.drawStringScaledMaxWidth(
480-
cat.desc,
484+
cat.getDescription(),
481485
ifr, innerLeft + 1, y + 40, true, innerRight - innerLeft - rightStuffLen - 10, 0xb0b0b0
482486
);
483487
}
@@ -865,7 +869,7 @@ public boolean mouseInput(int mouseX, int mouseY, MouseEvent mouseEvent) {
865869
if (mouseX >= x + 5 && mouseX <= x + 145 &&
866870
mouseY >= y + 70 + catY - 7 && mouseY <= y + 70 + catY + 7) {
867871
if (entry.getKey().equals(getSelectedCategory())) {
868-
if (entry.getValue().parent == null)
872+
if (entry.getValue().getParentCategoryId() == null)
869873
showSubcategories = !showSubcategories;
870874
} else {
871875
showSubcategories = true;

common/src/main/java/io/github/notenoughupdates/moulconfig/internal/ContextAware.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.github.notenoughupdates.moulconfig.internal;
22

33
import io.github.notenoughupdates.moulconfig.gui.GuiOptionEditor;
4+
import io.github.notenoughupdates.moulconfig.processor.HasDebugLocation;
45

56
import java.lang.reflect.Field;
67

@@ -18,10 +19,14 @@ public static <T> T wrapErrorWithContext(GuiOptionEditor editor, ContextAwareRun
1819
}
1920

2021
public static <T> T wrapErrorWithContext(Field field, ContextAwareRunnable<T> runnable) {
22+
return wrapErrorWithContext(field::toString, runnable);
23+
}
24+
25+
public static <T> T wrapErrorWithContext(HasDebugLocation field, ContextAwareRunnable<T> runnable) {
2126
try {
2227
return runnable.run();
2328
} catch (Exception e) {
24-
throw new ContextualException(e, field.toString());
29+
throw new ContextualException(e, field.getDebugDeclarationLocation());
2530
}
2631
}
2732

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package io.github.notenoughupdates.moulconfig.processor;
2+
3+
@FunctionalInterface
4+
public interface HasDebugLocation {
5+
String getDebugDeclarationLocation();
6+
}

common/src/main/java/io/github/notenoughupdates/moulconfig/processor/MoulConfigProcessor.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@
3939
public class MoulConfigProcessor<T extends Config> implements ConfigStructureReader {
4040

4141
private final T configBaseObject;
42-
private final LinkedHashMap<String, ProcessedCategory> categories = new LinkedHashMap<>();
43-
private ProcessedCategory currentCategory;
42+
private final LinkedHashMap<String, ProcessedCategoryImpl> categories = new LinkedHashMap<>();
43+
private ProcessedCategoryImpl currentCategory;
4444
private Stack<Integer> accordion = new Stack<>();
4545
private Stack<String> categoryPath = new Stack<>();
4646
@Getter
@@ -71,7 +71,7 @@ public void requireFinalized() {
7171

7272
@Override
7373
public void beginCategory(Object baseObject, Field field, String name, String description) {
74-
currentCategory = new ProcessedCategory(field, name, description);
74+
currentCategory = new ProcessedCategoryImpl(field, name, description);
7575
categories.put(currentCategory.getIdentifier(), currentCategory);
7676
}
7777

@@ -175,7 +175,7 @@ protected GuiOptionEditor createOptionGui(ProcessedOption processedOption, Field
175175
return null;
176176
}
177177

178-
public LinkedHashMap<String, ProcessedCategory> getAllCategories() {
178+
public LinkedHashMap<String, ? extends ProcessedCategory> getAllCategories() {
179179
requireFinalized();
180180
return this.categories;
181181
}

common/src/main/java/io/github/notenoughupdates/moulconfig/processor/ProcessedCategory.java

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,23 @@
2121
package io.github.notenoughupdates.moulconfig.processor;
2222

2323
import org.jetbrains.annotations.Nullable;
24+
import org.jetbrains.annotations.Unmodifiable;
2425

25-
import java.lang.reflect.Field;
26-
import java.util.ArrayList;
27-
import java.util.HashMap;
2826
import java.util.List;
2927
import java.util.Map;
3028

31-
public class ProcessedCategory { // TODO: replace with interface
32-
public final String name;
33-
public final String desc;
34-
public final Field reflectField;
35-
public final List<ProcessedOption> options = new ArrayList<>();
36-
public final Map<Integer, ProcessedOption> accordionAnchors = new HashMap<>();
37-
38-
public @Nullable String parent;
39-
40-
public String getIdentifier() {
41-
return reflectField.toString();
42-
}
43-
44-
public ProcessedCategory(Field field, String name, String desc) {
45-
this(field, name, desc, null);
46-
}
47-
48-
public ProcessedCategory(Field field, String name, String desc, @Nullable String parent) {
49-
this.reflectField = field;
50-
this.name = name;
51-
this.parent = parent;
52-
this.desc = desc;
53-
}
29+
public interface ProcessedCategory extends HasDebugLocation {
30+
String getDisplayName();
31+
32+
String getDescription();
33+
34+
String getIdentifier();
35+
36+
@Nullable String getParentCategoryId();
37+
38+
@Unmodifiable
39+
List<ProcessedOption> getOptions();
40+
41+
@Unmodifiable
42+
Map<Integer, ProcessedOption> getAccordionAnchors();
5443
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package io.github.notenoughupdates.moulconfig.processor;
2+
3+
import org.jetbrains.annotations.Nullable;
4+
import org.jetbrains.annotations.Unmodifiable;
5+
6+
import java.lang.reflect.Field;
7+
import java.util.ArrayList;
8+
import java.util.HashMap;
9+
import java.util.List;
10+
import java.util.Map;
11+
12+
public class ProcessedCategoryImpl implements ProcessedCategory {
13+
public final String name;
14+
public final String desc;
15+
public final Field reflectField;
16+
public final List<ProcessedOption> options = new ArrayList<>();
17+
public final Map<Integer, ProcessedOption> accordionAnchors = new HashMap<>();
18+
19+
public @Nullable String parent;
20+
21+
@Override
22+
public String getDisplayName() {
23+
return name;
24+
}
25+
26+
@Override
27+
public String getDescription() {
28+
return desc;
29+
}
30+
31+
@Override
32+
public String getDebugDeclarationLocation() {
33+
return reflectField.toString();
34+
}
35+
36+
@Override
37+
public String getIdentifier() {
38+
return reflectField.toString();
39+
}
40+
41+
@Override
42+
public @Nullable String getParentCategoryId() {
43+
return parent;
44+
}
45+
46+
@Override
47+
public @Unmodifiable List<ProcessedOption> getOptions() {
48+
return options;
49+
}
50+
51+
@Override
52+
public @Unmodifiable Map<Integer, ProcessedOption> getAccordionAnchors() {
53+
return accordionAnchors;
54+
}
55+
56+
public ProcessedCategoryImpl(Field field, String name, String desc) {
57+
this(field, name, desc, null);
58+
}
59+
60+
public ProcessedCategoryImpl(Field field, String name, String desc, @Nullable String parent) {
61+
this.reflectField = field;
62+
this.name = name;
63+
this.parent = parent;
64+
this.desc = desc;
65+
}
66+
}

common/src/main/java/io/github/notenoughupdates/moulconfig/processor/ProcessedOption.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public SearchTag[] getSearchTags() {
7171
public GuiOptionEditorAccordion getOwningAccordion() {
7272
if (owningAccordion == null && getAccordionId() >= 0) {
7373
owningAccordion = getCategory()
74-
.options
74+
.getOptions()
7575
.stream()
7676
.map(ProcessedOption::getEditor)
7777
.filter(it -> it instanceof GuiOptionEditorAccordion)

0 commit comments

Comments
 (0)