2025-03-11 14:09:49 +01:00
|
|
|
package game.gui.element;
|
|
|
|
|
|
|
|
import game.gui.Font;
|
|
|
|
import game.renderer.Drawing;
|
|
|
|
import game.util.Displayable;
|
|
|
|
import game.util.ExtMath;
|
|
|
|
import game.util.Formatter;
|
|
|
|
import game.util.Util;
|
|
|
|
import game.window.Button;
|
|
|
|
|
|
|
|
public class Dropdown<T> extends Element {
|
|
|
|
public class Handle extends Element {
|
|
|
|
private Handle(boolean up) {
|
|
|
|
super(Dropdown.this.pos_x, Dropdown.this.pos_y + (up ? -(Font.YGLYPH * Dropdown.this.values.length + 2) : Dropdown.this.size_y), Dropdown.this.size_x, Font.YGLYPH * Dropdown.this.values.length + 2, null);
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
for(T value : Dropdown.this.values) {
|
|
|
|
if(sb.length() > 0)
|
|
|
|
sb.append('\n');
|
|
|
|
sb.append(value instanceof Displayable ? ((Displayable)value).getDisplay() : value.toString());
|
|
|
|
}
|
|
|
|
this.setText(sb.toString());
|
|
|
|
this.visible = this.r_dirty = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void updateText() {
|
|
|
|
this.r_dirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected boolean isTextCenteredX() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected boolean isTextCenteredY() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean canClick() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void deselect() {
|
|
|
|
this.visible = false;
|
|
|
|
this.r_dirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void mouse(Button btn, int x, int y, boolean ctrl, boolean shift) {
|
|
|
|
Dropdown drop = Dropdown.this;
|
|
|
|
int prev = drop.value;
|
|
|
|
drop.value = (y - (this.pos_y + this.margin_y1)) * drop.values.length / (this.size_y - (this.margin_y1 + this.margin_y2));
|
|
|
|
drop.value = ExtMath.clampi(drop.value, 0, drop.values.length - 1);
|
|
|
|
if(drop.value != prev) {
|
|
|
|
drop.func.use(drop, drop.getValue());
|
|
|
|
drop.formatText();
|
2025-03-18 13:07:23 +01:00
|
|
|
this.playSound();
|
2025-03-11 14:09:49 +01:00
|
|
|
}
|
|
|
|
this.visible = false;
|
|
|
|
this.r_dirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void drawHover() {
|
|
|
|
int m = ((this.gm.mouse_y - (this.pos_y + this.margin_y1)) * Dropdown.this.values.length / (this.size_y - (this.margin_y1 + this.margin_y2)));
|
|
|
|
// if((sys.mouse_y - this.pos_y) < (this.size_y - this.margin_y2))
|
|
|
|
Drawing.drawRectColor(this.pos_x + this.margin_x1,
|
|
|
|
this.pos_y + this.margin_y1 + ExtMath.clampi(m, 0, Dropdown.this.values.length - 1) * ((this.size_y - (this.margin_y1 + this.margin_y2)) / Dropdown.this.values.length),
|
|
|
|
this.size_x - (this.margin_x1 + this.margin_x2),
|
|
|
|
(this.size_y - (this.margin_y1 + this.margin_y2)) / Dropdown.this.values.length, this.gm.style.hover);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static interface Callback<T> {
|
|
|
|
void use(Dropdown<T> elem, T value);
|
|
|
|
}
|
|
|
|
|
|
|
|
private final Callback<T> func;
|
|
|
|
private final T[] values;
|
|
|
|
private final Handle handle;
|
|
|
|
private final int def;
|
|
|
|
|
|
|
|
private int value;
|
|
|
|
|
|
|
|
public Dropdown(int x, int y, int w, int h, boolean up, T[] values, T def, T init, Callback<T> callback, Formatter<Dropdown<T>> formatter) {
|
|
|
|
super(x, y, w, h, formatter);
|
|
|
|
this.func = callback;
|
|
|
|
this.values = values;
|
|
|
|
this.def = Util.indexOfChecked(this.values, def);
|
|
|
|
this.value = Util.indexOfChecked(this.values, init);
|
|
|
|
this.handle = new Handle(up);
|
|
|
|
this.formatText();
|
|
|
|
}
|
|
|
|
|
|
|
|
public Dropdown(int x, int y, int w, int h, boolean up, T[] values, T def, T init, Callback<T> callback, final String text) {
|
|
|
|
this(x, y, w, h, up, values, def, init, callback, new Formatter<Dropdown<T>>() {
|
|
|
|
public String use(Dropdown<T> elem) {
|
|
|
|
T value = elem.getValue();
|
|
|
|
return String.format("%s: %s", text, value instanceof Displayable ? ((Displayable)value).getDisplay() : value.toString());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public T getValue() {
|
|
|
|
return this.values[this.value];
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setValue(T value) {
|
|
|
|
this.value = Util.indexOfChecked(this.values, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void mouse(Button btn, int x, int y, boolean ctrl, boolean shift) {
|
|
|
|
int prev = this.value;
|
|
|
|
if(ctrl || (btn == Button.MOUSE_MIDDLE)) {
|
|
|
|
if((this.value = this.def) != prev) {
|
|
|
|
this.func.use(this, this.getValue());
|
|
|
|
this.formatText();
|
2025-03-18 13:07:23 +01:00
|
|
|
this.playSound();
|
2025-03-11 14:09:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(this.gui != null) {
|
|
|
|
Handle drop = this.handle;
|
|
|
|
drop.visible = true;
|
|
|
|
drop.r_dirty = true;
|
|
|
|
this.gui.selected = drop;
|
2025-03-18 13:07:23 +01:00
|
|
|
this.playSound();
|
2025-03-11 14:09:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Handle getHandle() {
|
|
|
|
return this.handle;
|
|
|
|
}
|
|
|
|
}
|