composeDiagramContent function
List<DiagramContentSegment>
composeDiagramContent(
- Iterable<
ResolvedElement> visible, { - required bool hasBuilder(
- String widgetKey
- bool isDynamic(
- ResolvedElement element
Consumes already ordered visible elements, without a second spatial query. Text retains its existing final local pass; global ports/markers/chrome are deliberately outside this content stream.
Implementation
List<DiagramContentSegment> composeDiagramContent(
Iterable<ResolvedElement> visible, {
required bool Function(String widgetKey) hasBuilder,
bool Function(ResolvedElement element)? isDynamic,
}) {
final result = <DiagramContentSegment>[];
var pending = <DiagramContentOperation>[];
void flush() {
if (pending.isEmpty) return;
result.add(DiagramContentBand(pending));
pending = [];
}
bool? previousDynamic;
for (final element in visible) {
final dynamic = isDynamic?.call(element) ?? false;
if (previousDynamic != null && previousDynamic != dynamic) flush();
previousDynamic = dynamic;
if (element is! ResolvedShape ||
!element.definition.paintsContent ||
!element.widgetSlots.any(
(slot) => hasBuilder(slot.definition.widgetKey),
)) {
pending.add(DiagramContentOperation(element));
continue;
}
final mounted = {
for (final slot in element.widgetSlots)
if (hasBuilder(slot.definition.widgetKey)) slot.definition.id: slot,
};
pending.add(
DiagramContentOperation(element, phase: DiagramContentPhase.background),
);
var layers = <ResolvedShapeLayer>[];
void flushLayers() {
if (layers.isEmpty) return;
pending.add(
DiagramContentOperation(
element,
phase: DiagramContentPhase.layers,
layers: layers,
),
);
layers = [];
}
final resolvedById = {
for (final layer in element.layers) layer.definition.id: layer,
};
for (final definition in element.definition.layers) {
if (definition is ShapeWidgetLayerDefinition) {
final slot = mounted[definition.id];
if (slot != null) {
flushLayers();
flush();
result.add(DiagramWidgetPlacement(element, slot));
} else {
layers.addAll(
element.layers.where(
(layer) => layer.widgetSlotId == definition.id,
),
);
}
} else {
layers.add(resolvedById[definition.id]!);
}
}
flushLayers();
pending.add(
DiagramContentOperation(element, phase: DiagramContentPhase.border),
);
// Match the renderer's text admission. An absent resolved paragraph cannot
// paint text or its empty-edit placeholder; do not allocate/cache a no-op.
if (element.text != null) {
pending.add(
DiagramContentOperation(
element,
phase: DiagramContentPhase.text,
excludedWidgetSlotIds: mounted.keys,
),
);
}
}
flush();
return List.unmodifiable(result);
}