1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
package dev.isxander.yacl.api;
import com.google.common.collect.ImmutableList;
import dev.isxander.yacl.impl.OptionGroupImpl;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import org.apache.commons.lang3.Validate;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Serves as a separator between multiple chunks of options
* that may be too similar or too few to be placed in a separate {@link ConfigCategory}.
* Or maybe you just want your config to feel less dense.
*/
public interface OptionGroup {
/**
* Name of the option group, displayed as a separator in the option lists.
* Can be empty.
*/
Text name();
/**
* Tooltip displayed on hover.
*/
Text tooltip();
/**
* List of all options in the group
*/
@NotNull ImmutableList<? extends Option<?>> options();
/**
* Dictates if the group should be collapsed by default.
*/
boolean collapsed();
/**
* Always false when using the {@link Builder}
* used to not render the separator if true
*/
boolean isRoot();
/**
* Creates a builder to construct a {@link OptionGroup}
*/
static Builder createBuilder() {
return new Builder();
}
class Builder {
private Text name = Text.empty();
private final List<Text> tooltipLines = new ArrayList<>();
private final List<Option<?>> options = new ArrayList<>();
private boolean collapsed = false;
private Builder() {
}
/**
* Sets name of the group, can be {@link Text#empty()} to just separate options, like sodium.
*
* @see OptionGroup#name()
*/
public Builder name(@NotNull Text name) {
Validate.notNull(name, "`name` must not be null");
this.name = name;
return this;
}
/**
* Sets the tooltip to be used by the option group.
* Can be invoked twice to append more lines.
* No need to wrap the text yourself, the gui does this itself.
*
* @param tooltips text lines - merged with a new-line on {@link Builder#build()}.
*/
public Builder tooltip(@NotNull Text... tooltips) {
Validate.notEmpty(tooltips, "`tooltips` cannot be empty");
tooltipLines.addAll(List.of(tooltips));
return this;
}
/**
* Adds an option to group.
* To construct an option, use {@link Option#createBuilder(Class)}
*
* @see OptionGroup#options()
*/
public Builder option(@NotNull Option<?> option) {
Validate.notNull(option, "`option` must not be null");
if (option instanceof ListOption<?>)
throw new UnsupportedOperationException("List options must not be added as an option but a group!");
this.options.add(option);
return this;
}
/**
* Adds multiple options to group.
* To construct an option, use {@link Option#createBuilder(Class)}
*
* @see OptionGroup#options()
*/
public Builder options(@NotNull Collection<? extends Option<?>> options) {
Validate.notEmpty(options, "`options` must not be empty");
if (options.stream().anyMatch(ListOption.class::isInstance))
throw new UnsupportedOperationException("List options must not be added as an option but a group!");
this.options.addAll(options);
return this;
}
/**
* Dictates if the group should be collapsed by default
*
* @see OptionGroup#collapsed()
*/
public Builder collapsed(boolean collapsible) {
this.collapsed = collapsible;
return this;
}
public OptionGroup build() {
Validate.notEmpty(options, "`options` must not be empty to build `OptionGroup`");
MutableText concatenatedTooltip = Text.empty();
boolean first = true;
for (Text line : tooltipLines) {
if (!first) concatenatedTooltip.append("\n");
first = false;
concatenatedTooltip.append(line);
}
return new OptionGroupImpl(name, concatenatedTooltip, ImmutableList.copyOf(options), collapsed, false);
}
}
}
|