setPlainText method

EditResult setPlainText({
  1. required String elementId,
  2. required String text,
  3. String? storyId,
  4. String? slotId,
})

Replaces content with plain paragraphs, preserving the story identity. Formatting and list structure are reset. CRLF and CR become line breaks. Supply storyId for connectors with multiple labels. Admission enforces the slot's text and line limit, locks and host policies; success is one undo entry.

Implementation

EditResult setPlainText({
  required String elementId,
  required String text,
  String? storyId,
  String? slotId,
}) {
  final target = _resolveTarget(elementId, storyId);
  if (target == null) return _noTarget;
  if (_unavailable(target) case final denial?) return denial;
  final before = target.canonical.story;
  final slots = before.blocks.map((block) => block.effectiveSlotId).toSet();
  if ((slotId == null && slots.length > 1) ||
      (slotId != null && !slots.contains(slotId))) {
    return const EditResult.denied(
      code: DiagramDenialCode.unavailableTarget,
      reason: 'Select an existing text slot explicitly',
    );
  }
  final selectedSlot = slotId ?? slots.firstOrNull;
  final blocks = before.blocks
      .where((block) => block.effectiveSlotId == selectedSlot)
      .toList();
  final lines = text.split(RegExp(r'\r\n|\r|\n'));
  final replacements = [
    for (var i = 0; i < lines.length; i++)
      TextParagraph(
        id: i < blocks.length ? blocks[i].id : store.allocateId('paragraph'),
        role: blocks.firstOrNull?.role ?? TextRole.body,
        slotId: blocks.firstOrNull?.slotId,
        alignment: blocks.firstOrNull?.alignment ?? ParagraphAlignment.start,
        runs: [TextRun(lines[i])],
      ),
  ];
  var inserted = false;
  final updated = <TextParagraph>[];
  for (final block in before.blocks) {
    if (block.effectiveSlotId != selectedSlot) {
      updated.add(block);
    } else if (!inserted) {
      updated.addAll(replacements);
      inserted = true;
    }
  }
  if (!inserted) updated.addAll(replacements);
  final after = before.copyWith(blocks: updated);
  return replace(elementId: elementId, before: before, after: after);
}