oωo (owo-lib)

oωo (owo-lib)

17M Downloads

[owo-ui] When the accumulated size of Sizing should be 100%, it could be greater due to rounding

Zailer43 opened this issue · 0 comments

commented

Description

The Sizing#inflate method rounds values when using a sizing relative to screen size. This rounding can cause decimal values to be adjusted, resulting in multiple relative sizes potentially having a larger size than intended. This issue is particularly evident in an LTR flow layout, where components should sum to 100%.

While an LTR flow layout may seem like an unusual case for having components at 100%, in my scenario, I use it alongside an animation where components default to 50%. If they do not meet the minimum size, they expand to 100%, enhancing responsiveness for various screen sizes

public int inflate(int space, Function<Sizing, Integer> contentSizeFunction) {
return switch (this.method) {
case FIXED -> this.value;
case FILL, EXPAND -> Math.round((this.value / 100f) * space);
case CONTENT -> contentSizeFunction.apply(this) + this.value * 2;
};
}

Alternative Solution

One alternative solution could be to reduce each component's size by 1%

Attachments

Video_2024-09-23_18-34-44.mp4

Video code

@Override
    protected void build(FlowLayout rootComponent) {
        rootComponent.horizontalAlignment(HorizontalAlignment.CENTER).verticalAlignment(VerticalAlignment.CENTER);

        var ltrLayouts = Containers.verticalFlow(Sizing.fill(), Sizing.content());
        ltrLayouts.gap(4).margins(Insets.horizontal(10));

        for (int i = 2; i != 9; i++) {
            ltrLayouts.child(this.createLtrLayout(i));
        }

        Animation<?> animatable = ltrLayouts.horizontalSizing().animate(2000, Easing.LINEAR, Sizing.fill(50));
        AtomicBoolean animationState = new AtomicBoolean(false);

        var animateButton = Components.button(Text.literal("Animate"), buttonComponent -> {
            if (animationState.get()) {
                animatable.forwards();
            } else {
                animatable.reverse();
            }
            animationState.set(!animationState.get());
        });

        var addPadding = Components.button(Text.literal("+"), buttonComponent -> {
            Insets previousPadding = ltrLayouts.padding().get();
            ltrLayouts.padding(previousPadding.add(0, 0, 0, 1));
        });

        var removePadding = Components.button(Text.literal("-"), buttonComponent -> {
            Insets previousPadding = ltrLayouts.padding().get();
            if (previousPadding.right() > 0) {
                ltrLayouts.padding(previousPadding.add(0, 0, 0, -1));
            }
        });

        rootComponent.child(
                Containers.horizontalFlow(Sizing.content(), Sizing.content()).children(List.of(animateButton, addPadding, removePadding))
                .gap(4)
        );
        rootComponent.child(ltrLayouts);
    }

    private FlowLayout createLtrLayout(int childrenCount) {
        var result = Containers.ltrTextFlow(Sizing.expand(), Sizing.content());
        var list = this.divideByHundred(childrenCount);

        for (var percentage : list) {
            result.child(
                    Containers.horizontalFlow(Sizing.fill(percentage), Sizing.fixed(20))
                            .child(Components.label(Text.literal(percentage + "%")))
                            .surface(Surface.DARK_PANEL)
                            .padding(Insets.of(3))
            );
        }

        return result;
    }

    public List<Integer> divideByHundred(int count) {
        var result = new ArrayList<Integer>();
        if (count <= 0) {
            throw new IllegalArgumentException("Count must be greater than 0");
        }

        var base = 100 / count;
        var remainder = 100 % count;

        for (int i = 0; i < count; i++) {
            result.add(base);
            if (i < remainder) {
                result.set(i, result.get(i) + 1);
            }
        }

        return result;
    }

Versions

owo-lib = 0.12.14+1.21
fabric-api = 0.104.0+1.21.1