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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
|
package dev.isxander.yacl.api;
import com.google.common.collect.ImmutableSet;
import dev.isxander.yacl.impl.OptionImpl;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public interface Option<T> {
/**
* Name of the option
*/
@NotNull Component name();
/**
* Tooltip (or description) of the option.
* Rendered on hover.
*/
@NotNull Component tooltip();
/**
* Widget provider for a type of option.
*
* @see dev.isxander.yacl.gui.controllers
*/
@NotNull Controller<T> controller();
/**
* Binding for the option.
* Controls setting, getting and default value.
*
* @see Binding
*/
@NotNull Binding<T> binding();
/**
* If the option can be configured
*/
boolean available();
/**
* Sets if the option can be configured after being built
*
* @see Option#available()
*/
void setAvailable(boolean available);
/**
* Class of the option type.
* Used by some controllers.
*/
@NotNull Class<T> typeClass();
/**
* Tasks that needs to be executed upon applying changes.
*/
@NotNull ImmutableSet<OptionFlag> flags();
/**
* Checks if the pending value is not equal to the current set value
*/
boolean changed();
/**
* Value in the GUI, ready to set the actual bound value or be undone.
*/
@NotNull T pendingValue();
/**
* Sets the pending value
*/
void requestSet(T value);
/**
* Applies the pending value to the bound value.
* Cannot be undone.
*
* @return if there were changes to apply {@link Option#changed()}
*/
boolean applyValue();
/**
* Sets the pending value to the bound value.
*/
void forgetPendingValue();
/**
* Sets the pending value to the default bound value.
*/
void requestSetDefault();
/**
* Checks if the current pending value is equal to its default value
*/
boolean isPendingValueDefault();
default boolean canResetToDefault() {
return true;
}
/**
* Adds a listener for when the pending value changes
*/
void addListener(BiConsumer<Option<T>, T> changedListener);
/**
* Creates a builder to construct an {@link Option}
*
* @param <T> type of the option's value
* @param typeClass used to capture the type
*/
static <T> Builder<T> createBuilder(Class<T> typeClass) {
return new OptionImpl.BuilderImpl<>(typeClass);
}
interface Builder<T> {
/**
* Sets the name to be used by the option.
*
* @see Option#name()
*/
Builder<T> name(@NotNull Component name);
/**
* Sets the tooltip to be used by the option.
* No need to wrap the text yourself, the gui does this itself.
*
* @param tooltipGetter function to get tooltip depending on value {@link Builder#build()}.
*/
@SuppressWarnings("unchecked")
Builder<T> tooltip(@NotNull Function<T, Component>... tooltipGetter);
/**
* Sets the tooltip to be used by the option.
* 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()}.
*/
Builder<T> tooltip(@NotNull Component... tooltips);
/**
* Sets the controller for the option.
* This is how you interact and change the options.
*
* @see dev.isxander.yacl.gui.controllers
*/
Builder<T> controller(@NotNull Function<Option<T>, Controller<T>> control);
/**
* Sets the binding for the option.
* Used for default, getter and setter.
*
* @see Binding
*/
Builder<T> binding(@NotNull Binding<T> binding);
/**
* Sets the binding for the option.
* Shorthand of {@link Binding#generic(Object, Supplier, Consumer)}
*
* @param def default value of the option, used to reset
* @param getter should return the current value of the option
* @param setter should set the option to the supplied value
* @see Binding
*/
Builder<T> binding(@NotNull T def, @NotNull Supplier<@NotNull T> getter, @NotNull Consumer<@NotNull T> setter);
/**
* Sets if the option can be configured
*
* @see Option#available()
*/
Builder<T> available(boolean available);
/**
* Adds a flag to the option.
* Upon applying changes, all flags are executed.
* {@link Option#flags()}
*/
Builder<T> flag(@NotNull OptionFlag... flag);
/**
* Adds a flag to the option.
* Upon applying changes, all flags are executed.
* {@link Option#flags()}
*/
Builder<T> flags(@NotNull Collection<OptionFlag> flags);
/**
* Instantly invokes the binder's setter when modified in the GUI.
* Prevents the user from undoing the change
* <p>
* Does not support {@link Option#flags()}!
*/
Builder<T> instant(boolean instant);
/**
* Adds a listener to the option. Invoked upon changing the pending value.
*
* @see Option#addListener(BiConsumer)
*/
Builder<T> listener(@NotNull BiConsumer<Option<T>, T> listener);
/**
* Adds multiple listeners to the option. Invoked upon changing the pending value.
*
* @see Option#addListener(BiConsumer)
*/
Builder<T> listeners(@NotNull Collection<BiConsumer<Option<T>, T>> listeners);
Option<T> build();
}
}
|