Skip to content

Commit

Permalink
Corrected Local Bounds for Absolute Positioning
Browse files Browse the repository at this point in the history
Yoga adds the offsets of a node into
the bounds when that node is positioned
absolutely. This removes the offsets
from the reported bounds in these
cases, since this is confusing
behavior that usually needs to be
accounted for downstream.
  • Loading branch information
danielperano committed Feb 22, 2024
1 parent fbe5388 commit 1e5bbc6
Showing 1 changed file with 32 additions and 2 deletions.
34 changes: 32 additions & 2 deletions Obsidian/src/main/java/myworld/obsidian/layout/LayoutEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,20 +95,50 @@ public float getHeight(Component component){
return LAYOUT_UNDEFINED;
}

protected boolean isAbsolute(Component component){
var isAbsolute = component.layout().positionType().is(PositionType.ABSOLUTE);
if(!isAbsolute && component.hasParent()){
return isAbsolute(component.getParent());
}
return isAbsolute;
}

public Bounds2D getLocalBounds(Component component){
var node = getYogaNode(component);
if(node != null){
var isAbsolute = isAbsolute(component);
var offsets = component.layout().offsets().get(Offsets.ZERO);

var rawWidth = YGNodeLayoutGetWidth(node);
var rawHeight = YGNodeLayoutGetHeight(node);

var width = rawWidth;
var height = rawHeight;

if(isAbsolute){
// Yoga considers the offsets to be part of the width/height when absolute positioning is used,
// but this is very awkward for downstream consumers since it requires different layout logic.
// Instead, compute the visual bounds as usual without regard for offsets when absolute positioning
// is used.
width -= Math.abs(maybeAutoToPixels(offsets.left(), width) + maybeAutoToPixels(offsets.right(), width));
height -= Math.abs(maybeAutoToPixels(offsets.top(), height) + maybeAutoToPixels(offsets.bottom(), height));
}

return new Bounds2D(
new Point2D(
YGNodeLayoutGetLeft(node),
YGNodeLayoutGetTop(node)),
YGNodeLayoutGetWidth(node),
YGNodeLayoutGetHeight(node)
width,
height
);
}
return Bounds2D.UNDEFINED;
}

protected float maybeAutoToPixels(Distance d, float pxSize){
return d.equals(Layout.AUTO) ? 0f : d.toPixels(pxSize);
}

public Bounds2D getSceneBounds(Component component){
var bounds = getLocalBounds(component);
float x = bounds.origin().x();
Expand Down

0 comments on commit 1e5bbc6

Please sign in to comment.