Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,21 @@ static IKey comp(@NotNull IKey... keys) {
* @return dynamic text key
*/
static IKey dynamic(@NotNull Supplier<@NotNull Component> getter) {
Component c = getter.get();
if (c instanceof MutableComponent m) {
return dynamicKey(() -> IKey.lang(m));
} else {
return dynamicKey(() -> IKey.lang(c.copy()));
}
}

/**
* Creates a dynamic text key.
*
* @param getter key supplier
* @return dynamic text key
*/
static IKey dynamicKey(@NotNull Supplier<@NotNull IKey> getter) {
return new DynamicKey(getter);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package com.gregtechceu.gtceu.api.mui.base.value;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* An interface that is implemented on {@link IValue} and {@link com.gregtechceu.gtceu.api.mui.value.sync.SyncHandler
* SyncHandler} for easier
* validation and setters.
*/
@ApiStatus.NonExtendable
public interface ISyncOrValue {

/**
* A sync handler or value representing null.
*/
ISyncOrValue EMPTY = new ISyncOrValue() {

@Override
public <T> @Nullable T castNullable(Class<T> type) {
return null;
}

@Override
public boolean isTypeOrEmpty(Class<?> type) {
return true;
}
};

/**
* Returns the given sync handler or value or {@link #EMPTY} if null.
*
* @param syncOrValue sync handler or value
* @return a non-null representation of the given sync handler or value
*/
@NotNull
static ISyncOrValue orEmpty(@Nullable ISyncOrValue syncOrValue) {
return syncOrValue != null ? syncOrValue : EMPTY;
}

/**
* Returns if this sync handler or value is an instance of the given type or if this represents null. This is
* useful, when the value or
* sync handler can be null in the widget.
*
* @param type type to check for
* @return if this sync handler or value is an instance of the type or empty
*/
default boolean isTypeOrEmpty(Class<?> type) {
return type.isAssignableFrom(getClass());
}

/**
* Casts this sync handler or value to the given type or null if this isn't a subtype of the given type.
*
* @param type type to cast this sync handle or value to
* @param <T> type to cast to
* @return this cast sync handler or value
*/
@Nullable
@SuppressWarnings("unchecked")
default <T> T castNullable(Class<T> type) {
return type.isAssignableFrom(getClass()) ? (T) this : null;
}

/**
* Casts this sync handler or value to a {@link IValue IValue&lt;V&gt;} if it is a value handler and the containing
* value is of type
* {@link V} else null.
*
* @param valueType expected type of the containing value
* @param <V> expected type of the containing value
* @return a {@link IValue IValue&lt;V&gt;} if types match or null
*/
@Nullable
default <V> IValue<V> castValueNullable(Class<V> valueType) {
return null;
}

/**
* Casts this sync handler or value to the given type or throws an exception if this isn't a subtype of the given
* type.
*
* @param type type to cast this sync handle or value to
* @param <T> type to cast to
* @return this cast sync handler or value
* @throws IllegalStateException if this is not a subtype of the given type
*/
default <T> T castOrThrow(Class<T> type) {
T t = castNullable(type);
if (t == null) {
if (!isSyncHandler() && !isValueHandler()) {
throw new IllegalStateException("Empty sync handler or value can't be used for anything.");
}
String self = isSyncHandler() ? "sync handler" : "value";
throw new IllegalStateException("Can't cast " + self + " of type '" + getClass().getSimpleName() +
"' to type '" + type.getSimpleName() + "'.");
}
return t;
}

/**
* Returns if the containing value of this is of the given type. If this is not a value it will always return false.
*
* @param type expected value type
* @return if the containing value of this is of the given type
*/
default boolean isValueOfType(Class<?> type) {
return false;
}

/**
* @return if this is a sync handler (false if this represents null)
*/
default boolean isSyncHandler() {
return false;
}

/**
* @return if this is a value handler (false if this represents null)
*/
default boolean isValueHandler() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* @param <T> value type
*/
public interface IValue<T> {
public interface IValue<T> extends ISyncOrValue {

/**
* Gets the current value.
Expand All @@ -20,4 +20,21 @@ public interface IValue<T> {
* @param value new value
*/
void setValue(T value);

Class<T> getValueType();

default boolean isValueOfType(Class<?> type) {
return type.isAssignableFrom(getValueType());
}

@SuppressWarnings("unchecked")
@Override
default <V> IValue<V> castValueNullable(Class<V> valueType) {
return isValueOfType(valueType) ? (IValue<V>) this : null;
}

@Override
default boolean isValueHandler() {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.gregtechceu.gtceu.api.mui.base.widget;

import com.gregtechceu.gtceu.api.mui.base.value.ISyncOrValue;
import com.gregtechceu.gtceu.api.mui.value.sync.GenericSyncValue;
import com.gregtechceu.gtceu.api.mui.value.sync.ModularSyncManager;
import com.gregtechceu.gtceu.api.mui.value.sync.SyncHandler;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

Expand All @@ -28,25 +30,58 @@ default W getThis() {
* Called when this widget gets initialised or when this widget is added to the gui
*
* @param syncManager sync manager
* @param late true if this is called some time after the widget tree of the parent has been initialised
* @param late if this is called at any point after the panel this widget belongs to opened
*/
void initialiseSyncHandler(ModularSyncManager syncManager, boolean late);

/**
* Checks if the received sync handler is valid for this widget.
* <b>Synced widgets must override this!</b>
*
* @param syncHandler received sync handler
* @return true if sync handler is valid
* @deprecated use {@link #isValidSyncOrValue(ISyncOrValue)}
*/
@ApiStatus.ScheduledForRemoval(inVersion = "3.2.0")
@Deprecated
default boolean isValidSyncHandler(SyncHandler syncHandler) {
return false;
}

/**
* Returns if the given value or sync handler is valid for this widget. This is usually a call to
* {@link ISyncOrValue#isTypeOrEmpty(Class)}. If the widget must specify a value (disallow null) instanceof check
* can be used. You can
* check for primitive types which don't have a dedicated {@link com.gregtechceu.gtceu.api.mui.base.value.IValue
* IValue} interface with
* {@link ISyncOrValue#isValueOfType(Class)}.
*
* @param syncOrValue a sync handler or a value, but never null
* @return if the value or sync handler is valid for this class
*/
default boolean isValidSyncOrValue(@NotNull ISyncOrValue syncOrValue) {
return !(syncOrValue instanceof SyncHandler syncHandler) || isValidSyncHandler(syncHandler);
}

/**
* Checks if the given sync handler is valid for this widget and throws an exception if not.
* Override {@link #isValidSyncHandler(SyncHandler)}
*
* @param syncHandler given sync handler
* @throws IllegalStateException if the given sync handler is invalid for this widget.
*/
@ApiStatus.NonExtendable
default void checkValidSyncOrValue(ISyncOrValue syncHandler) {
if (!isValidSyncOrValue(syncHandler)) {
throw new IllegalStateException(
"SyncHandler of type '" + syncHandler.getClass().getSimpleName() + "' is not valid " +
"for widget '" + this + "'.");
}
}

@ApiStatus.ScheduledForRemoval(inVersion = "3.2.0")
@Deprecated
default <T> T castIfTypeElseNull(SyncHandler syncHandler, Class<T> clazz) {
return castIfTypeElseNull(syncHandler, clazz, null);
}

@ApiStatus.ScheduledForRemoval(inVersion = "3.2.0")
@Deprecated
@SuppressWarnings("unchecked")
default <T> T castIfTypeElseNull(SyncHandler syncHandler, Class<T> clazz, @Nullable Consumer<T> setup) {
if (syncHandler != null && clazz.isAssignableFrom(syncHandler.getClass())) {
Expand All @@ -57,10 +92,14 @@ default <T> T castIfTypeElseNull(SyncHandler syncHandler, Class<T> clazz, @Nulla
return null;
}

@ApiStatus.ScheduledForRemoval(inVersion = "3.2.0")
@Deprecated
default <T> GenericSyncValue<T> castIfTypeGenericElseNull(SyncHandler syncHandler, Class<T> clazz) {
return castIfTypeGenericElseNull(syncHandler, clazz, null);
}

@ApiStatus.ScheduledForRemoval(inVersion = "3.2.0")
@Deprecated
default <T> GenericSyncValue<T> castIfTypeGenericElseNull(SyncHandler syncHandler, Class<T> clazz,
@Nullable Consumer<GenericSyncValue<T>> setup) {
if (syncHandler instanceof GenericSyncValue<?> genericSyncValue && genericSyncValue.isOfType(clazz)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ default void draw(ModularGuiContext context) {
void drawForeground(ModularGuiContext context);

default void transform(IViewportStack stack) {
stack.translate(getArea().rx, getArea().ry, getArea().getPanelLayer() * 20);
stack.translate(getArea().rx, getArea().ry, 0);
}

default Object getAdditionalHoverInfo(IViewportStack viewportStack, int mouseX, int mouseY) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,41 @@
package com.gregtechceu.gtceu.api.mui.drawable.text;

import net.minecraft.network.chat.Component;
import com.gregtechceu.gtceu.api.mui.base.drawable.IKey;

import net.minecraft.network.chat.MutableComponent;

import java.util.Objects;
import org.jetbrains.annotations.Nullable;

import java.util.function.Supplier;

public class DynamicKey extends BaseKey {

private final Supplier<MutableComponent> supplier;

public DynamicKey(Supplier<Component> supplier) {
Objects.requireNonNull(supplier.get(), "IKey returns a null string!");
this.supplier = () -> {
Component c = supplier.get();
if (c instanceof MutableComponent m) {
return m;
} else {
return c.copy();
}
};
private final Supplier<IKey> supplier;

public DynamicKey(Supplier<IKey> supplier) {
// Objects.requireNonNull(supplier.get(), "IKey returns a null string!");
this.supplier = supplier;
}

@Override
public MutableComponent get() {
return this.supplier.get();
return toString(false, null);
}

@Override
public MutableComponent getFormatted(@Nullable FormattingState parentFormatting) {
// formatting is prepended to each key
return toString(true, parentFormatting);
}

private MutableComponent toString(boolean formatted, @Nullable FormattingState parentFormatting) {
IKey key = this.supplier.get();
if (key == null) key = IKey.EMPTY;
if (formatted) {
// merge parent formatting and this formatting to no lose info
return key.getFormatted(FormattingState.merge(parentFormatting, getFormatting()));
} else {
return key.get();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ protected int getStartY(float height) {

protected int getStartY(float maxHeight, float height) {
if (this.alignment.y > 0 && maxHeight > 0 && height != maxHeight) {
return (int) (this.y + (maxHeight * this.alignment.y) - height * this.alignment.y);
return this.y + Math.round(maxHeight * this.alignment.y) - Math.round(height * this.alignment.y);
}
return this.y;
}
Expand All @@ -255,7 +255,8 @@ protected int getStartX(float lineWidth) {

protected int getStartX(float maxWidth, float lineWidth) {
if (this.alignment.x > 0 && maxWidth > 0) {
return Math.max(this.x, (int) (this.x + (maxWidth * this.alignment.x) - lineWidth * this.alignment.x));
return Math.max(this.x,
this.x + Math.round(maxWidth * this.alignment.x) - Math.round(lineWidth * this.alignment.x));
}
return this.x;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import net.minecraft.world.level.Level;

import lombok.Getter;
import org.jetbrains.annotations.NotNull;

import java.util.Objects;

Expand All @@ -21,10 +22,11 @@
*/
public class GuiData {

@NotNull
@Getter
private final Player player;

public GuiData(Player player) {
public GuiData(@NotNull Player player) {
this.player = Objects.requireNonNull(player);
}

Expand Down
Loading