Skip to content
This repository has been archived by the owner on Oct 14, 2024. It is now read-only.

feat: Recalculate layout #23

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
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
16 changes: 15 additions & 1 deletion flutter/lib/src/layout/node_properties.dart
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,20 @@ class NodeProperties {

bool isCalculated() {
return !_mapper.yGNodeLayoutGetWidth(_node).isNaN &&
!_mapper.yGNodeLayoutGetHeight(_node).isNaN;
!_mapper.yGNodeLayoutGetHeight(_node).isNaN &&
!_mapper.yGNodeIsDirty(_node)
;
}

void removeAllChildren() {
_mapper.yGNodeRemoveAllChildren(node);
}

void dirtyAllDescendants() {
_mapper.yGNodeMarkDirtyAndPropagateToDescendants(_node);
}

bool isDirty() {
return _mapper.yGNodeIsDirty(_node);
}
}
76 changes: 70 additions & 6 deletions flutter/lib/src/layout/yoga_render.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,24 @@ class YogaParentData extends ContainerBoxParentData<RenderBox> {
String toString() => '${super.toString()}; nodeProperties=$nodeProperties';
}

Widget _observeLayoutChanges(Widget child) {
return MeasureSize(
child: child
);
}

/// Class responsible to measure any flutter widget by the NodeProperties.
/// This can only be placed inside a YogaLayout widget and cannot have another
/// YogaNode as a direct child.
/// Use this class to wrap around any flutter widget. The yoga will be able
/// to calculate the layout size and the children offsets,
/// given this wrapped widget's size.
class YogaNode extends ParentDataWidget<YogaParentData> {
const YogaNode({
YogaNode({
Key? key,
required this.nodeProperties,
required Widget child,
}) : super(key: key, child: child);
}) : super(key: key, child: _observeLayoutChanges(child));

final NodeProperties nodeProperties;

Expand Down Expand Up @@ -75,6 +81,47 @@ class YogaNode extends ParentDataWidget<YogaParentData> {
}
}

class MeasureSizeRenderObject extends RenderProxyBox {
Size oldSize = Size.zero;

@override
void performLayout() {
super.performLayout();

Size newSize = child?.size ?? Size.zero;
if (newSize == oldSize) return;

debugPrint("Size changed $child oldSize: ${oldSize.toString()} newSize: ${newSize.toString()}");
oldSize = newSize;

WidgetsBinding.instance?.addPostFrameCallback((_) {
_recalculateLayout(parent);
});
}

void _recalculateLayout(AbstractNode? targetParent) {
if (targetParent is RenderYoga) {
//FIXME Trigger rebuild if we have more than one container ancestor. example Container(container( image) ) )
targetParent.nodeProperties.dirtyAllDescendants();
targetParent.nodeProperties.removeAllChildren();
}
}
}

class MeasureSize extends SingleChildRenderObjectWidget {

const MeasureSize({
Key? key,
required Widget child,
}) : super(key: key, child: child);

@override
RenderObject createRenderObject(BuildContext context) {
return MeasureSizeRenderObject();
}

}

class RenderYoga extends RenderBox
with
ContainerRenderObjectMixin<RenderBox, YogaParentData>,
Expand Down Expand Up @@ -145,7 +192,11 @@ class RenderYoga extends RenderBox
void _attachNodesFromWidgetsHierarchy(RenderYoga renderYoga) {
final children = renderYoga.getChildrenAsList();
for (var i = 0; i < children.length; i++) {
final child = children[i];
var child = children[i];
if (child is MeasureSizeRenderObject && child.child is RenderYoga) {
child = child.child!;
}

if (child is RenderYoga) {
renderYoga.nodeProperties.insertChildAt(child.nodeProperties, i);
_attachNodesFromWidgetsHierarchy(child);
Expand All @@ -172,8 +223,14 @@ class RenderYoga extends RenderBox

void _applyLayoutToWidgetsHierarchy(List<RenderBox> children) {
for (var i = 0; i < children.length; i++) {
final child = children[i];
var child = children[i];
RenderBox? originalChild = null;
final yogaParentData = child.parentData as YogaParentData;
if (child is MeasureSizeRenderObject && child.child is RenderYoga) {
originalChild = child;
child = child.child!;
}

late Pointer<YGNode> node;
if (child is RenderYoga) {
node = child.nodeProperties.node;
Expand All @@ -191,7 +248,12 @@ class RenderYoga extends RenderBox
_helper.getLayoutHeight(node),
),
);
child.layout(childConstraints, parentUsesSize: true);

if(originalChild != null) {
originalChild.layout(childConstraints, parentUsesSize: true);
} else {
child.layout(childConstraints, parentUsesSize: true);
}
_helper.removeNodeReference(node);
}
}
Expand All @@ -215,7 +277,9 @@ class YogaLayout extends MultiChildRenderObjectWidget {
Key? key,
required this.nodeProperties,
List<Widget> children = const <Widget>[],
}) : super(key: key, children: children);
}) : super(key: key,
children: children,
);

final NodeProperties nodeProperties;

Expand Down