From f28dda7b4ada32d90cdbcc1da719d378750527d6 Mon Sep 17 00:00:00 2001 From: Hernand Azevedo Date: Fri, 22 Oct 2021 13:26:37 -0300 Subject: [PATCH 1/5] :sparkles: Initial implementation of size change listening to reacalculate layout. Signed-off-by: Hernand Azevedo --- flutter/lib/src/layout/node_properties.dart | 12 ++++- flutter/lib/src/layout/yoga_render.dart | 60 +++++++++++++++++++-- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/flutter/lib/src/layout/node_properties.dart b/flutter/lib/src/layout/node_properties.dart index 6c0c5a9b2c..82cd3e97d9 100644 --- a/flutter/lib/src/layout/node_properties.dart +++ b/flutter/lib/src/layout/node_properties.dart @@ -371,6 +371,16 @@ 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); } } diff --git a/flutter/lib/src/layout/yoga_render.dart b/flutter/lib/src/layout/yoga_render.dart index 024f3b557c..0d0fd3dd65 100644 --- a/flutter/lib/src/layout/yoga_render.dart +++ b/flutter/lib/src/layout/yoga_render.dart @@ -33,6 +33,17 @@ class YogaParentData extends ContainerBoxParentData { String toString() => '${super.toString()}; nodeProperties=$nodeProperties'; } +Widget _observeLayoutChanges(Widget child) { + //FIXME understand how to ubserve size for YogaLayout Widgets, and make them be renderized by the logic + if(child.toString().toLowerCase().startsWith("beaglecontainer-") || + child.toString().toLowerCase().startsWith("beaglesimpleform-")) { + return 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. @@ -40,11 +51,11 @@ class YogaParentData extends ContainerBoxParentData { /// to calculate the layout size and the children offsets, /// given this wrapped widget's size. class YogaNode extends ParentDataWidget { - 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; @@ -75,6 +86,46 @@ class YogaNode extends ParentDataWidget { } } +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) { + 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, @@ -215,7 +266,10 @@ class YogaLayout extends MultiChildRenderObjectWidget { Key? key, required this.nodeProperties, List children = const [], - }) : super(key: key, children: children); + }) : super(key: key, + children: children, + // children: children.map((child) => _observeLayoutChanges(child)).toList() + ); final NodeProperties nodeProperties; From 5da360158bea1ecd97bf03d5701190dc9adaa17b Mon Sep 17 00:00:00 2001 From: Hernand Azevedo Date: Thu, 28 Oct 2021 10:13:41 -0300 Subject: [PATCH 2/5] :sparkles: Adds recalculate layout for MeasureSize in yoga logic Signed-off-by: Hernand Azevedo --- flutter/lib/src/layout/node_properties.dart | 4 ++ flutter/lib/src/layout/yoga_render.dart | 51 +++++++++++++++------ 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/flutter/lib/src/layout/node_properties.dart b/flutter/lib/src/layout/node_properties.dart index 82cd3e97d9..83b3e18d9c 100644 --- a/flutter/lib/src/layout/node_properties.dart +++ b/flutter/lib/src/layout/node_properties.dart @@ -383,4 +383,8 @@ class NodeProperties { void dirtyAllDescendants() { _mapper.yGNodeMarkDirtyAndPropagateToDescendants(_node); } + + bool isDirty() { + return _mapper.yGNodeIsDirty(_node); + } } diff --git a/flutter/lib/src/layout/yoga_render.dart b/flutter/lib/src/layout/yoga_render.dart index 0d0fd3dd65..aa3338273e 100644 --- a/flutter/lib/src/layout/yoga_render.dart +++ b/flutter/lib/src/layout/yoga_render.dart @@ -34,14 +34,9 @@ class YogaParentData extends ContainerBoxParentData { } Widget _observeLayoutChanges(Widget child) { - //FIXME understand how to ubserve size for YogaLayout Widgets, and make them be renderized by the logic - if(child.toString().toLowerCase().startsWith("beaglecontainer-") || - child.toString().toLowerCase().startsWith("beaglesimpleform-")) { - return child; - } - return MeasureSize( - child: child - ); + return MeasureSize( + child: child + ); } /// Class responsible to measure any flutter widget by the NodeProperties. @@ -106,8 +101,16 @@ class MeasureSizeRenderObject extends RenderProxyBox { void _recalculateLayout(AbstractNode? targetParent) { if (targetParent is RenderYoga) { - targetParent.nodeProperties.dirtyAllDescendants(); - targetParent.nodeProperties.removeAllChildren(); + // if (targetParent.parent is MeasureSizeRenderObject && + // (targetParent.parent as MeasureSizeRenderObject).parent is RenderYoga) { + // final superParent = (targetParent.parent as MeasureSizeRenderObject).parent as RenderYoga; + // superParent.nodeProperties.dirtyAllDescendants(); + // superParent.nodeProperties.removeAllChildren(); + // } else { + //FIXME Trigger rebuild if we have more than one container ancestor. example Container(container( image) ) ) + targetParent.nodeProperties.dirtyAllDescendants(); + targetParent.nodeProperties.removeAllChildren(); + // } } } } @@ -164,6 +167,9 @@ class RenderYoga extends RenderBox @override Size computeDryLayout(BoxConstraints constraints) { if (!nodeProperties.isCalculated()) { + if(nodeProperties.isDirty() && nodeProperties.getChildCount() > 0) { + nodeProperties.removeAllChildren(); + } _attachNodesFromWidgetsHierarchy(this); nodeProperties.calculateLayout(YGUndefined, YGUndefined); } @@ -176,6 +182,9 @@ class RenderYoga extends RenderBox @override void performLayout() { if (!nodeProperties.isCalculated()) { + if(nodeProperties.isDirty() && nodeProperties.getChildCount() > 0) { + nodeProperties.removeAllChildren(); + } _attachNodesFromWidgetsHierarchy(this); final maxWidth = constraints.maxWidth.isInfinite ? YGUndefined @@ -196,7 +205,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); @@ -223,8 +236,14 @@ class RenderYoga extends RenderBox void _applyLayoutToWidgetsHierarchy(List 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 node; if (child is RenderYoga) { node = child.nodeProperties.node; @@ -242,7 +261,13 @@ class RenderYoga extends RenderBox _helper.getLayoutHeight(node), ), ); - child.layout(childConstraints, parentUsesSize: true); + + if(originalChild != null) { + child.layout(childConstraints, parentUsesSize: true); + originalChild.layout(childConstraints, parentUsesSize: true); + } else { + child.layout(childConstraints, parentUsesSize: true); + } _helper.removeNodeReference(node); } } From cf9f6f27522462bade93fd361460ac01c83b19a2 Mon Sep 17 00:00:00 2001 From: Hernand Azevedo Date: Fri, 29 Oct 2021 16:54:40 -0300 Subject: [PATCH 3/5] :sparkles: Adds Size handler for YogaLayouts Signed-off-by: Hernand Azevedo --- flutter/lib/src/layout/yoga_render.dart | 8 ++++---- flutter/lib/yoga_engine.dart | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flutter/lib/src/layout/yoga_render.dart b/flutter/lib/src/layout/yoga_render.dart index aa3338273e..37e2b8d1cd 100644 --- a/flutter/lib/src/layout/yoga_render.dart +++ b/flutter/lib/src/layout/yoga_render.dart @@ -206,8 +206,8 @@ class RenderYoga extends RenderBox final children = renderYoga.getChildrenAsList(); for (var i = 0; i < children.length; i++) { var child = children[i]; - if (child is MeasureSizeRenderObject && child.child is RenderYoga) { - child = (child).child!; + if (child is MeasureSizeRenderObject && child.child is MeasureSizeRenderObject && (child.child as MeasureSizeRenderObject).child is RenderYoga) { + child = (child.child as MeasureSizeRenderObject).child!; } if (child is RenderYoga) { @@ -239,9 +239,9 @@ class RenderYoga extends RenderBox var child = children[i]; RenderBox? originalChild = null; final yogaParentData = child.parentData as YogaParentData; - if (child is MeasureSizeRenderObject && child.child is RenderYoga) { + if (child is MeasureSizeRenderObject && child.child is MeasureSizeRenderObject && (child.child as MeasureSizeRenderObject).child is RenderYoga) { originalChild = child; - child = (child).child!; + child = (child.child as MeasureSizeRenderObject).child!; } late Pointer node; diff --git a/flutter/lib/yoga_engine.dart b/flutter/lib/yoga_engine.dart index d8f0746498..8859f1a466 100644 --- a/flutter/lib/yoga_engine.dart +++ b/flutter/lib/yoga_engine.dart @@ -17,5 +17,5 @@ export 'package:yoga_engine/src/yoga_initializer.dart' show Yoga; export 'package:yoga_engine/src/layout/node_properties.dart'; export 'package:yoga_engine/src/layout/yoga_render.dart' - show YogaNode, YogaLayout; + show YogaNode, YogaLayout, MeasureSize; export 'package:yoga_engine/src/ffi/types.dart'; From 385502b9dd7bbcc05de57c19f5fe421f6422babb Mon Sep 17 00:00:00 2001 From: Hernand Azevedo Date: Fri, 5 Nov 2021 15:09:12 -0300 Subject: [PATCH 4/5] :sparkles: Implements recalculate layout for image. Signed-off-by: Hernand Azevedo --- flutter/lib/src/layout/yoga_render.dart | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/flutter/lib/src/layout/yoga_render.dart b/flutter/lib/src/layout/yoga_render.dart index 37e2b8d1cd..759254e972 100644 --- a/flutter/lib/src/layout/yoga_render.dart +++ b/flutter/lib/src/layout/yoga_render.dart @@ -91,7 +91,7 @@ class MeasureSizeRenderObject extends RenderProxyBox { Size newSize = child?.size ?? Size.zero; if (newSize == oldSize) return; - debugPrint("Size changed ${child} oldSize: ${oldSize.toString()} newSize: ${newSize.toString()}"); + debugPrint("Size changed $child oldSize: ${oldSize.toString()} newSize: ${newSize.toString()}"); oldSize = newSize; WidgetsBinding.instance?.addPostFrameCallback((_) { @@ -101,16 +101,9 @@ class MeasureSizeRenderObject extends RenderProxyBox { void _recalculateLayout(AbstractNode? targetParent) { if (targetParent is RenderYoga) { - // if (targetParent.parent is MeasureSizeRenderObject && - // (targetParent.parent as MeasureSizeRenderObject).parent is RenderYoga) { - // final superParent = (targetParent.parent as MeasureSizeRenderObject).parent as RenderYoga; - // superParent.nodeProperties.dirtyAllDescendants(); - // superParent.nodeProperties.removeAllChildren(); - // } else { //FIXME Trigger rebuild if we have more than one container ancestor. example Container(container( image) ) ) targetParent.nodeProperties.dirtyAllDescendants(); targetParent.nodeProperties.removeAllChildren(); - // } } } } @@ -167,9 +160,6 @@ class RenderYoga extends RenderBox @override Size computeDryLayout(BoxConstraints constraints) { if (!nodeProperties.isCalculated()) { - if(nodeProperties.isDirty() && nodeProperties.getChildCount() > 0) { - nodeProperties.removeAllChildren(); - } _attachNodesFromWidgetsHierarchy(this); nodeProperties.calculateLayout(YGUndefined, YGUndefined); } @@ -182,9 +172,6 @@ class RenderYoga extends RenderBox @override void performLayout() { if (!nodeProperties.isCalculated()) { - if(nodeProperties.isDirty() && nodeProperties.getChildCount() > 0) { - nodeProperties.removeAllChildren(); - } _attachNodesFromWidgetsHierarchy(this); final maxWidth = constraints.maxWidth.isInfinite ? YGUndefined @@ -206,8 +193,8 @@ class RenderYoga extends RenderBox final children = renderYoga.getChildrenAsList(); for (var i = 0; i < children.length; i++) { var child = children[i]; - if (child is MeasureSizeRenderObject && child.child is MeasureSizeRenderObject && (child.child as MeasureSizeRenderObject).child is RenderYoga) { - child = (child.child as MeasureSizeRenderObject).child!; + if (child is MeasureSizeRenderObject && child.child is RenderYoga) { + child = child.child!; } if (child is RenderYoga) { @@ -239,9 +226,9 @@ class RenderYoga extends RenderBox var child = children[i]; RenderBox? originalChild = null; final yogaParentData = child.parentData as YogaParentData; - if (child is MeasureSizeRenderObject && child.child is MeasureSizeRenderObject && (child.child as MeasureSizeRenderObject).child is RenderYoga) { + if (child is MeasureSizeRenderObject && child.child is RenderYoga) { originalChild = child; - child = (child.child as MeasureSizeRenderObject).child!; + child = child.child!; } late Pointer node; @@ -263,7 +250,6 @@ class RenderYoga extends RenderBox ); if(originalChild != null) { - child.layout(childConstraints, parentUsesSize: true); originalChild.layout(childConstraints, parentUsesSize: true); } else { child.layout(childConstraints, parentUsesSize: true); @@ -293,7 +279,6 @@ class YogaLayout extends MultiChildRenderObjectWidget { List children = const [], }) : super(key: key, children: children, - // children: children.map((child) => _observeLayoutChanges(child)).toList() ); final NodeProperties nodeProperties; From 2a1f606b931242cc38332c5844d85963ec5d683a Mon Sep 17 00:00:00 2001 From: Hernand Azevedo Date: Fri, 5 Nov 2021 15:09:51 -0300 Subject: [PATCH 5/5] :sparkles: Implements recalculate layout for image. Signed-off-by: Hernand Azevedo --- flutter/lib/yoga_engine.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/lib/yoga_engine.dart b/flutter/lib/yoga_engine.dart index 8859f1a466..d8f0746498 100644 --- a/flutter/lib/yoga_engine.dart +++ b/flutter/lib/yoga_engine.dart @@ -17,5 +17,5 @@ export 'package:yoga_engine/src/yoga_initializer.dart' show Yoga; export 'package:yoga_engine/src/layout/node_properties.dart'; export 'package:yoga_engine/src/layout/yoga_render.dart' - show YogaNode, YogaLayout, MeasureSize; + show YogaNode, YogaLayout; export 'package:yoga_engine/src/ffi/types.dart';