Skip to content

Commit 3306b58

Browse files
committed
auto re-layout layout widgets on child change enabled state
1 parent 7bb155e commit 3306b58

File tree

9 files changed

+101
-10
lines changed

9 files changed

+101
-10
lines changed

src/main/java/com/cleanroommc/modularui/api/layout/ILayoutWidget.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package com.cleanroommc.modularui.api.layout;
22

3+
import com.cleanroommc.modularui.api.widget.INotifyEnabled;
34
import com.cleanroommc.modularui.api.widget.IWidget;
45

56
/**
67
* This is responsible for laying out widgets.
78
*/
8-
public interface ILayoutWidget {
9+
public interface ILayoutWidget extends INotifyEnabled {
910

1011
/**
1112
* Called after the children tried to calculate their size.
@@ -29,4 +30,10 @@ default void postLayoutWidgets() {}
2930
default boolean shouldIgnoreChildSize(IWidget child) {
3031
return false;
3132
}
33+
34+
@Override
35+
default void onChildChangeEnabled(IWidget child, boolean enabled) {
36+
layoutWidgets();
37+
postLayoutWidgets();
38+
}
3239
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.cleanroommc.modularui.api.widget;
2+
3+
public interface INotifyEnabled {
4+
5+
void onChildChangeEnabled(IWidget child, boolean enabled);
6+
7+
}

src/main/java/com/cleanroommc/modularui/screen/ModularPanel.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.cleanroommc.modularui.value.sync.PanelSyncManager;
2525
import com.cleanroommc.modularui.value.sync.SyncHandler;
2626
import com.cleanroommc.modularui.widget.ParentWidget;
27+
import com.cleanroommc.modularui.widget.WidgetTree;
2728
import com.cleanroommc.modularui.widget.sizer.Area;
2829
import com.cleanroommc.modularui.widgets.SlotGroupWidget;
2930

@@ -219,6 +220,8 @@ public void onOpen(ModularScreen screen) {
219220
this.screen = screen;
220221
getArea().z(1);
221222
initialise(this);
223+
// call first tick after everything is initialised
224+
WidgetTree.onUpdate(this);
222225
if (!isMainPanel() && shouldAnimate()) {
223226
getAnimator().onFinish(() -> {});
224227
getAnimator().reset();

src/main/java/com/cleanroommc/modularui/test/EventHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public static void onItemUse(PlayerInteractEvent.RightClickItem event) {
2222
.screenScale(0.5f)
2323
.open(new TestGui());*/
2424
//ClientGUI.open(new ResizerTest());
25-
ClientGUI.open(new TestGui());
25+
ClientGUI.open(new TestGuis());
2626
}
2727
}
2828

src/main/java/com/cleanroommc/modularui/test/TestGui.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.cleanroommc.modularui.ModularUI;
44
import com.cleanroommc.modularui.api.IPanelHandler;
5+
import com.cleanroommc.modularui.api.IThemeApi;
56
import com.cleanroommc.modularui.api.drawable.IDrawable;
67
import com.cleanroommc.modularui.api.drawable.IKey;
78
import com.cleanroommc.modularui.drawable.GuiTextures;
@@ -52,7 +53,7 @@ public void onClose() {
5253
.child(item -> new Row()
5354
.child(new Widget<>()
5455
.addTooltipLine(line)
55-
.background(GuiTextures.BUTTON_CLEAN)
56+
.widgetTheme(IThemeApi.BUTTON)
5657
.overlay(IKey.str(line))
5758
.expanded().heightRel(1f))
5859
.child(new ButtonWidget<>()

src/main/java/com/cleanroommc/modularui/test/TestGuis.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.cleanroommc.modularui.animation.Animator;
55
import com.cleanroommc.modularui.animation.IAnimator;
66
import com.cleanroommc.modularui.animation.Wait;
7+
import com.cleanroommc.modularui.api.IThemeApi;
78
import com.cleanroommc.modularui.api.drawable.IDrawable;
89
import com.cleanroommc.modularui.api.drawable.IKey;
910
import com.cleanroommc.modularui.api.widget.IWidget;
@@ -19,6 +20,8 @@
1920
import com.cleanroommc.modularui.utils.fakeworld.ArraySchema;
2021
import com.cleanroommc.modularui.utils.fakeworld.ISchema;
2122
import com.cleanroommc.modularui.widget.DraggableWidget;
23+
import com.cleanroommc.modularui.widget.Widget;
24+
import com.cleanroommc.modularui.widgets.ListWidget;
2225
import com.cleanroommc.modularui.widgets.RichTextWidget;
2326
import com.cleanroommc.modularui.widgets.SchemaWidget;
2427
import com.cleanroommc.modularui.widgets.SortableListWidget;
@@ -46,7 +49,7 @@ public class TestGuis extends CustomModularScreen {
4649

4750
@Override
4851
public @NotNull ModularPanel buildUI(ModularGuiContext context) {
49-
return buildPostTheLogAnimationUI(context);
52+
return buildListUi(context);
5053
}
5154

5255
public @NotNull ModularPanel buildAnimationUI(ModularGuiContext context) {
@@ -254,4 +257,23 @@ public class TestGuis extends CustomModularScreen {
254257
.size(16));
255258
return panel;
256259
}
260+
261+
public ModularPanel buildListUi(ModularGuiContext context) {
262+
Random rnd = new Random();
263+
return ModularPanel.defaultPanel("list", 100, 150)
264+
.padding(7)
265+
.child(new ListWidget<>()
266+
.sizeRel(1f)
267+
.collapseDisabledChild()
268+
.children(12, i -> new Widget<>()
269+
.widthRel(1f)
270+
.height(16)
271+
.widgetTheme(IThemeApi.BUTTON)
272+
.overlay(IKey.str(String.valueOf(i + 1)))
273+
.onUpdateListener(w -> {
274+
if (rnd.nextDouble() < 0.05) {
275+
w.setEnabled(!w.isEnabled());
276+
}
277+
})));
278+
}
257279
}

src/main/java/com/cleanroommc/modularui/widget/Widget.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ public final void initialise(@NotNull IWidget parent) {
113113
}
114114
}
115115
afterInit();
116-
onUpdate();
117116
this.requiresResize = false;
118117
}
119118

@@ -826,7 +825,12 @@ public boolean isEnabled() {
826825
*/
827826
@Override
828827
public void setEnabled(boolean enabled) {
829-
this.enabled = enabled;
828+
if (this.enabled != enabled) {
829+
this.enabled = enabled;
830+
if (isValid() && getParent() instanceof INotifyEnabled notifyEnabled) {
831+
notifyEnabled.onChildChangeEnabled(this, enabled);
832+
}
833+
}
830834
}
831835

832836
public boolean isExcludeAreaInJei() {

src/main/java/com/cleanroommc/modularui/widgets/ListWidget.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class ListWidget<I extends IWidget, W extends ListWidget<I, W>> extends A
2727
private ScrollData scrollData;
2828
private IIcon childSeparator;
2929
private final IntList separatorPositions = new IntArrayList();
30-
private boolean collapseDisabledChild = false;
30+
private boolean collapseDisabledChild = true;
3131

3232
public ListWidget() {
3333
super(null, null);
@@ -85,6 +85,9 @@ public void layoutWidgets() {
8585
}
8686
this.separatorPositions.add(p);
8787
p += separatorSize;
88+
if (isValid()) {
89+
widget.flex().applyPos(widget);
90+
}
8891
}
8992
getScrollData().setScrollSize(p + getArea().getPadding().getEnd(axis));
9093
}
@@ -94,6 +97,13 @@ public boolean shouldIgnoreChildSize(IWidget child) {
9497
return this.collapseDisabledChild && !child.isEnabled();
9598
}
9699

100+
@Override
101+
public void onChildChangeEnabled(IWidget child, boolean enabled) {
102+
if (this.collapseDisabledChild) {
103+
ILayoutWidget.super.onChildChangeEnabled(child, enabled);
104+
}
105+
}
106+
97107
@Override
98108
public boolean addChild(I child, int index) {
99109
return super.addChild(child, index);
@@ -167,10 +177,22 @@ public W children(int amount, IntFunction<I> widgetCreator) {
167177
}
168178

169179
/**
170-
* Configures this widget to collapse disabled child widgets.
180+
* Sets if disabled children should be collapsed.
171181
*/
172182
public W collapseDisabledChild() {
173-
this.collapseDisabledChild = true;
183+
return collapseDisabledChild(true);
184+
}
185+
186+
/**
187+
* Sets if disabled children should be collapsed. This means that if a child changes enabled state, this widget gets notified and
188+
* re-layouts its children. Children which are disabled will not be considered during layout, so that the list will not appear to have
189+
* empty spots. This is enabled by default on lists.
190+
*
191+
* @param doCollapse true if disabled children should be collapsed.
192+
* @return this
193+
*/
194+
public W collapseDisabledChild(boolean doCollapse) {
195+
this.collapseDisabledChild = doCollapse;
174196
return getThis();
175197
}
176198
}

src/main/java/com/cleanroommc/modularui/widgets/layout/Flow.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,14 @@ public void postLayoutWidgets() {
153153
}
154154
}
155155
widget.getArea().setRelativePoint(other, crossAxisPos);
156+
widget.getArea().setPoint(other, getArea().getPoint(other) + crossAxisPos);
156157
widget.resizer().setPosResized(other, true);
157158
widget.resizer().setMarginPaddingApplied(other, true);
158159
}
160+
if (isValid()) {
161+
// we changed rel pos, but we need to calculate the new absolute pos and other stuff
162+
widget.flex().applyPos(widget);
163+
}
159164
}
160165
}
161166

@@ -164,6 +169,13 @@ public boolean shouldIgnoreChildSize(IWidget child) {
164169
return this.collapseDisabledChild && !child.isEnabled();
165170
}
166171

172+
@Override
173+
public void onChildChangeEnabled(IWidget child, boolean enabled) {
174+
if (this.collapseDisabledChild) {
175+
ILayoutWidget.super.onChildChangeEnabled(child, enabled);
176+
}
177+
}
178+
167179
public Flow crossAxisAlignment(Alignment.CrossAxis caa) {
168180
this.caa = caa;
169181
return this;
@@ -180,13 +192,26 @@ public Flow childPadding(int spaceBetween) {
180192
}
181193

182194
/**
183-
* Configures this widget to collapse disabled child widgets.
195+
* Sets if disabled children should be collapsed.
184196
*/
185197
public Flow collapseDisabledChild() {
186198
this.collapseDisabledChild = true;
187199
return this;
188200
}
189201

202+
/**
203+
* Sets if disabled children should be collapsed. This means that if a child changes enabled state, this widget gets notified and
204+
* re-layouts its children. Children which are disabled will not be considered during layout, so that the flow will not appear to have
205+
* empty spots. This is disabled by default on Flow.
206+
*
207+
* @param doCollapse true if disabled children should be collapsed.
208+
* @return this
209+
*/
210+
public Flow collapseDisabledChild(boolean doCollapse) {
211+
this.collapseDisabledChild = doCollapse;
212+
return this;
213+
}
214+
190215
public GuiAxis getAxis() {
191216
return axis;
192217
}

0 commit comments

Comments
 (0)