couple view and controller + offset working

This commit is contained in:
2025-07-02 01:21:45 +00:00
parent a7ea05c00d
commit 0e4125a583
5 changed files with 149 additions and 24 deletions
+43 -13
View File
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:infinite_lazy_2d_grid/core/controller.dart';
import 'background.dart';
@@ -10,19 +11,30 @@ import 'background.dart';
/// An infinite canvas that places all the children at the specified positions.
class CanvasView extends StatelessWidget {
final List<Offset> ssPositions; // screen space positions;
final List<Widget> children; // children, in the same order as positions
final CanvasBackground canvasBackground;
final CanvasController controller;
const CanvasView({required this.ssPositions, required this.children, required this.canvasBackground, super.key})
: assert(children.length == ssPositions.length, 'Children and positions must have the same length');
const CanvasView({required this.controller, required this.canvasBackground, super.key});
@override
Widget build(BuildContext context) {
return Container(
color: canvasBackground.bgColor,
child: GestureDetector(
child: _CanvasRenderObject(canvasBackground: canvasBackground, ssPositions: ssPositions, children: children),
onScaleUpdate: controller.handleGesture,
child: ListenableBuilder(
listenable: controller,
builder: (_, _) {
final childrenWithPositions = controller.widgetsWithScreenPositions();
final ssPositions = childrenWithPositions.map((e) => e.$1).toList();
final children = childrenWithPositions.map((e) => e.$2).toList();
return _CanvasRenderObject(
canvasBackground: canvasBackground,
ssPositions: ssPositions,
children: children,
);
},
),
),
);
}
@@ -46,7 +58,9 @@ class _CanvasRenderObject extends MultiChildRenderObjectWidget {
@override
void updateRenderObject(BuildContext context, _CanvasRenderBox renderObject) {
// static for now
renderObject
..ssPositions = ssPositions
..canvasBackground = canvasBackground;
}
}
@@ -57,10 +71,12 @@ class _CanvasRenderBox extends RenderBox
with
ContainerRenderObjectMixin<RenderBox, _WidgetParentData>,
RenderBoxContainerDefaultsMixin<RenderBox, _WidgetParentData> {
final CanvasBackground canvasBackground;
final List<Offset> ssPositions;
CanvasBackground _canvasBackground;
List<Offset> _ssPositions;
_CanvasRenderBox({required this.ssPositions, required this.canvasBackground});
_CanvasRenderBox({required ssPositions, required canvasBackground})
: _ssPositions = ssPositions,
_canvasBackground = canvasBackground;
@override
void setupParentData(RenderBox child) {
@@ -69,6 +85,20 @@ class _CanvasRenderBox extends RenderBox
}
}
set ssPositions(List<Offset> ssPositions) {
if (_ssPositions != ssPositions) {
_ssPositions = ssPositions;
markNeedsPaint();
}
}
set canvasBackground(CanvasBackground canvasBackground) {
if (_canvasBackground != canvasBackground) {
_canvasBackground = canvasBackground;
markNeedsPaint();
}
}
@override
void performLayout() {
size = constraints.biggest; // expand as much as possible for the parent
@@ -89,12 +119,12 @@ class _CanvasRenderBox extends RenderBox
final canvas = context.canvas;
// use the canvas background painter, pass it the canvas and that should handle drawing the background
canvasBackground.paint(canvas, size);
_canvasBackground.paint(canvas, size);
RenderBox? child = firstChild;
for (int idx = 0; child != null; idx++) {
final _WidgetParentData parentData = child.parentData! as _WidgetParentData;
context.paintChild(child, ssPositions[idx]);
context.paintChild(child, _ssPositions[idx]);
child = parentData.nextSibling;
}
}
@@ -109,11 +139,11 @@ class _CanvasRenderBox extends RenderBox
// Check children in reverse order (last painted = first hit)
RenderBox? child = lastChild;
for (int idx = ssPositions.length - 1; child != null; idx--) {
for (int idx = _ssPositions.length - 1; child != null; idx--) {
final _WidgetParentData parentData = child.parentData! as _WidgetParentData;
// Transform the hit position relative to the child's position
final childPosition = ssHitPosition - ssPositions[idx];
final childPosition = ssHitPosition - _ssPositions[idx];
if (child.hitTest(BoxHitTestResult.wrap(result), position: childPosition)) {
return true;