Skip to content
Draft

3.1 #189

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
305cf6e
context menu things
brachy84 Nov 1, 2025
6c6bbac
Merge branch 'master' into 3.1
brachy84 Nov 1, 2025
dd0fb96
Merge branch 'master' into 3.1
brachy84 Nov 9, 2025
3ecd149
Merge branch 'master' into 3.1
brachy84 Nov 12, 2025
d752265
a bunch of things
brachy84 Nov 14, 2025
172d35a
Merge branch 'master' into 3.1
brachy84 Dec 10, 2025
599d2e9
Merge branch 'master' into 3.1
brachy84 Jan 4, 2026
71e1fcb
Merge branch 'master' into 3.1
brachy84 Jan 8, 2026
2854250
Merge branch 'master' into 3.1
brachy84 Jan 18, 2026
ebf9071
Merge branch 'master' into 3.1
brachy84 Jan 23, 2026
df67908
Merge branch 'master' into 3.1
brachy84 Jan 27, 2026
6b1343e
compiles
brachy84 Jan 27, 2026
ccbd6f4
finally works
brachy84 Jan 27, 2026
b839d72
context menus finally working again
brachy84 Jan 28, 2026
6f3d778
mroe stuff
brachy84 Jan 28, 2026
27c2785
new delegating widget, remove obsolete ContextMenuOption
brachy84 Jan 28, 2026
62d8bba
panels can have their own theme
brachy84 Jan 28, 2026
542437c
improve context menu theme
brachy84 Jan 28, 2026
b816281
deprecate single arg ModularScreen ctor
brachy84 Jan 30, 2026
83d8c8e
open overlays via new event & deprecate OverlayManager & OverlayHandler
brachy84 Jan 30, 2026
9fe6b26
clean up
brachy84 Jan 30, 2026
0c5ebfd
more clean up
brachy84 Jan 30, 2026
e8725ed
dropdown widget
brachy84 Jan 30, 2026
56bc9c5
javadoc
brachy84 Jan 31, 2026
1fb4e3c
relativeToScreen works again
brachy84 Jan 31, 2026
8f5cd56
reorganize IWidget
brachy84 Jan 31, 2026
19d68cb
fixes & cleanup
brachy84 Jan 31, 2026
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
4 changes: 0 additions & 4 deletions src/main/java/com/cleanroommc/modularui/ClientProxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import com.cleanroommc.modularui.keybind.KeyBindHandler;
import com.cleanroommc.modularui.screen.ClientScreenHandler;
import com.cleanroommc.modularui.test.EventHandler;
import com.cleanroommc.modularui.test.OverlayTest;
import com.cleanroommc.modularui.test.TestItem;
import com.cleanroommc.modularui.theme.ThemeManager;
import com.cleanroommc.modularui.theme.ThemeReloadCommand;
Expand Down Expand Up @@ -70,9 +69,6 @@ void preInit(FMLPreInitializationEvent event) {
testKey = new KeyBinding("key.test", KeyConflictContext.IN_GAME, Keyboard.KEY_NUMPAD4, "key.categories.modularui");
ClientRegistry.registerKeyBinding(testKey);
}
if (ModularUIConfig.enableTestOverlays) {
OverlayTest.init();
}

DrawableSerialization.init();
RenderingRegistry.registerEntityRenderingHandler(HoloScreenEntity.class, ScreenEntityRender::new);
Expand Down
13 changes: 5 additions & 8 deletions src/main/java/com/cleanroommc/modularui/GuiError.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package com.cleanroommc.modularui;

import com.cleanroommc.modularui.api.widget.IGuiElement;

import com.cleanroommc.modularui.network.NetworkHandler;

import com.cleanroommc.modularui.api.widget.IWidget;
import com.cleanroommc.modularui.network.NetworkUtils;

import org.apache.logging.log4j.Level;
Expand All @@ -12,18 +9,18 @@

public class GuiError {

public static void throwNew(IGuiElement guiElement, Type type, String msg) {
public static void throwNew(IWidget guiElement, Type type, String msg) {
if (NetworkUtils.isClient()) {
GuiErrorHandler.INSTANCE.pushError(guiElement, type, msg);
}
}

private final Level level = Level.ERROR;
private final String msg;
private final IGuiElement reference;
private final IWidget reference;
private final Type type;

protected GuiError(String msg, IGuiElement reference, Type type) {
protected GuiError(String msg, IWidget reference, Type type) {
this.msg = msg;
this.reference = reference;
this.type = type;
Expand All @@ -33,7 +30,7 @@ public Level getLevel() {
return level;
}

public IGuiElement getReference() {
public IWidget getReference() {
return reference;
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/cleanroommc/modularui/GuiErrorHandler.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.cleanroommc.modularui;

import com.cleanroommc.modularui.api.widget.IGuiElement;
import com.cleanroommc.modularui.api.widget.IWidget;

import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
Expand All @@ -25,7 +25,7 @@ public void clear() {
this.errors.clear();
}

void pushError(IGuiElement reference, GuiError.Type type, String msg) {
void pushError(IWidget reference, GuiError.Type type, String msg) {
GuiError error = new GuiError(msg, reference, type);
if (this.errorSet.add(error)) {
ModularUI.LOGGER.log(error.getLevel(), error);
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/cleanroommc/modularui/ModularUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.relauncher.FMLLaunchHandler;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand Down Expand Up @@ -36,6 +37,8 @@ public class ModularUI {
serverSide = "com.cleanroommc.modularui.CommonProxy")
public static CommonProxy proxy;

public static final boolean isDev = FMLLaunchHandler.isDeobfuscatedEnvironment();

@Mod.Instance
public static ModularUI INSTANCE;

Expand Down
4 changes: 3 additions & 1 deletion src/main/java/com/cleanroommc/modularui/api/IGuiHolder.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.cleanroommc.modularui.api;

import com.cleanroommc.modularui.ModularUI;
import com.cleanroommc.modularui.factory.GuiData;
import com.cleanroommc.modularui.screen.ModularPanel;
import com.cleanroommc.modularui.screen.ModularScreen;
Expand All @@ -24,7 +25,8 @@ public interface IGuiHolder<T extends GuiData> {
*/
@SideOnly(Side.CLIENT)
default ModularScreen createScreen(T data, ModularPanel mainPanel) {
return new ModularScreen(mainPanel);
ModularUI.LOGGER.warn("IGuiHolder.createScreen() should be overridden to pass you own mod id to the ModularScreen. In future versions this method must be overridden or else it will crash!");
return new ModularScreen(ModularUI.ID, mainPanel);
}

/**
Expand Down
30 changes: 28 additions & 2 deletions src/main/java/com/cleanroommc/modularui/api/IThemeApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.cleanroommc.modularui.api.drawable.IDrawable;
import com.cleanroommc.modularui.drawable.GuiTextures;
import com.cleanroommc.modularui.drawable.Scrollbar;
import com.cleanroommc.modularui.screen.ModularPanel;
import com.cleanroommc.modularui.screen.ModularScreen;
import com.cleanroommc.modularui.theme.SelectableTheme;
import com.cleanroommc.modularui.theme.SlotTheme;
Expand Down Expand Up @@ -167,7 +168,32 @@ default void registerTheme(ThemeBuilder<?> themeBuilder) {
* @param defaultTheme default theme if no theme was found
* @return the registered theme for the given screen or the given default theme or {@link #getDefaultTheme()}
*/
ITheme getThemeForScreen(String owner, String name, @Nullable String defaultTheme);
default ITheme getThemeForScreen(String owner, String name, @Nullable String defaultTheme, @Nullable String fallbackTheme) {
return getThemeForScreen(owner, name, null, defaultTheme, fallbackTheme);
}

/**
* Gets the appropriate theme for a screen.
*
* @param owner owner of the screen
* @param name name of the screen
* @param panel the name
* @param defaultTheme default theme if no theme was found
* @return the registered theme for the given screen or the given default theme or {@link #getDefaultTheme()}
*/
ITheme getThemeForScreen(String owner, String name, @Nullable String panel, @Nullable String defaultTheme, @Nullable String fallbackTheme);

/**
* Gets the appropriate theme for a specific panel.
*
* @param panel the panel to find a theme for
* @param defaultTheme default theme if no theme was found
* @return the registered theme for the given screen or the given default theme or {@link #getDefaultTheme()}
*/
default ITheme getThemeForScreen(ModularPanel panel, @Nullable String defaultTheme) {
ModularScreen screen = panel.getScreen();
return getThemeForScreen(screen.getOwner(), screen.getName(), panel.getName(), defaultTheme, screen.getThemeOverride());
}

/**
* Gets the appropriate theme for a screen.
Expand All @@ -177,7 +203,7 @@ default void registerTheme(ThemeBuilder<?> themeBuilder) {
* @return the registered theme for the given screen or the given default theme or {@link #getDefaultTheme()}
*/
default ITheme getThemeForScreen(ModularScreen screen, @Nullable String defaultTheme) {
return getThemeForScreen(screen.getOwner(), screen.getName(), defaultTheme);
return getThemeForScreen(screen.getOwner(), screen.getName(), defaultTheme, null);
}

/**
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/com/cleanroommc/modularui/api/ITreeNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.cleanroommc.modularui.api;

import java.util.List;

public interface ITreeNode<T extends ITreeNode<T>> {

T getParent();

default boolean hasParent() {
return getParent() != null;
}

List<T> getChildren();

default boolean hasChildren() {
return !getChildren().isEmpty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.cleanroommc.modularui.api.layout;

import com.cleanroommc.modularui.api.GuiAxis;
import com.cleanroommc.modularui.widget.sizer.Area;

public interface IResizeParent {

/**
* @return area of the element
*/
Area getArea();

/**
* @return true if the relative x position is calculated
*/
boolean isXCalculated();

/**
* @return true if the relative y position is calculated
*/
boolean isYCalculated();

/**
* @return true if the width is calculated
*/
boolean isWidthCalculated();

/**
* @return true if the height is calculated
*/
boolean isHeightCalculated();

boolean areChildrenCalculated();

boolean isLayoutDone();

boolean canRelayout(boolean isParentLayout);

default boolean isSizeCalculated(GuiAxis axis) {
return axis.isHorizontal() ? isWidthCalculated() : isHeightCalculated();
}

default boolean isPosCalculated(GuiAxis axis) {
return axis.isHorizontal() ? isXCalculated() : isYCalculated();
}

/**
* @return true if the relative position and size are fully calculated
*/
default boolean isSelfFullyCalculated(boolean isParentLayout) {
return isSelfFullyCalculated() && !canRelayout(isParentLayout);
}

default boolean isSelfFullyCalculated() {
return isXCalculated() && isYCalculated() && isWidthCalculated() && isHeightCalculated();
}

default boolean isFullyCalculated() {
return isSelfFullyCalculated() && areChildrenCalculated() && isLayoutDone();
}

default boolean isFullyCalculated(boolean isParentLayout) {
return isFullyCalculated() && !canRelayout(isParentLayout);
}

/**
* @return true if margin and padding are applied on the x-axis
*/
boolean isXMarginPaddingApplied();

/**
* @return true if margin and padding are applied on the y-axis
*/
boolean isYMarginPaddingApplied();
}
Original file line number Diff line number Diff line change
@@ -1,103 +1,38 @@
package com.cleanroommc.modularui.api.layout;

import com.cleanroommc.modularui.api.GuiAxis;
import com.cleanroommc.modularui.api.widget.IGuiElement;
import com.cleanroommc.modularui.widget.sizer.Area;

/**
* An interface that handles resizing of widgets.
* Usually this interface is not implemented by the users of this library or will even interact with it.
*/
public interface IResizeable {
public interface IResizeable extends IResizeParent {

/**
* Called once before resizing
*/
void initResizing();
void initResizing(boolean onOpen);

/**
* Resizes the given element
*
* @param guiElement element to resize
* @param isParentLayout if the parent is a layout widget
* @return true if element is fully resized
*/
boolean resize(IGuiElement guiElement, boolean isParentLayout);
boolean resize(boolean isParentLayout);

/**
* Called if {@link #resize(IGuiElement, boolean)} returned false after children have been resized.
* Called if {@link #resize(boolean)} returned false after children have been resized.
*
* @param guiElement element to resize
* @return if element is fully resized
*/
boolean postResize(IGuiElement guiElement);
boolean postResize();

/**
* Called after all elements in the tree are resized and the absolute positions needs to be calculated from the
* relative postion.
*
* @param guiElement element that was resized
*/
default void applyPos(IGuiElement guiElement) {}

/**
* @return area of the element
*/
// TODO doesnt fit with the other api methods in this interface
Area getArea();

/**
* @return true if the relative x position is calculated
*/
boolean isXCalculated();

/**
* @return true if the relative y position is calculated
*/
boolean isYCalculated();

/**
* @return true if the width is calculated
*/
boolean isWidthCalculated();

/**
* @return true if the height is calculated
*/
boolean isHeightCalculated();

boolean areChildrenCalculated();

boolean isLayoutDone();

default boolean isSizeCalculated(GuiAxis axis) {
return axis.isHorizontal() ? isWidthCalculated() : isHeightCalculated();
}

default boolean isPosCalculated(GuiAxis axis) {
return axis.isHorizontal() ? isXCalculated() : isYCalculated();
}

/**
* @return true if the relative position and size are fully calculated
*/
default boolean isSelfFullyCalculated(boolean isParentLayout) {
return isSelfFullyCalculated() && !canRelayout(isParentLayout);
}

default boolean isSelfFullyCalculated() {
return isXCalculated() && isYCalculated() && isWidthCalculated() && isHeightCalculated();
}

default boolean isFullyCalculated() {
return isSelfFullyCalculated() && areChildrenCalculated() && isLayoutDone();
}

default boolean isFullyCalculated(boolean isParentLayout) {
return isSelfFullyCalculated(isParentLayout) && areChildrenCalculated() && isLayoutDone();
}

boolean canRelayout(boolean isParentLayout);
default void applyPos() {}

void setChildrenResized(boolean resized);

Expand Down Expand Up @@ -182,14 +117,4 @@ default void setMarginPaddingApplied(GuiAxis axis, boolean b) {
setYMarginPaddingApplied(b);
}
}

/**
* @return true if margin and padding are applied on the x-axis
*/
boolean isXMarginPaddingApplied();

/**
* @return true if margin and padding are applied on the y-axis
*/
boolean isYMarginPaddingApplied();
}
Loading