showDefineBitFieldsDialog function

Future<List<BitFieldDef>?> showDefineBitFieldsDialog(
  1. BuildContext context, {
  2. required String signalName,
  3. required int width,
  4. List<BitFieldDef>? existingDefs,
})

Show a dialog to define named bit-field slices on a signal.

Returns the parsed BitFieldDef list, or null if cancelled/empty.

Implementation

Future<List<BitFieldDef>?> showDefineBitFieldsDialog(
  BuildContext context, {
  required String signalName,
  required int width,
  List<BitFieldDef>? existingDefs,
}) async {
  final maxBit = width - 1;

  // Pre-fill with existing definitions if re-editing; append a trailing
  // newline and place the cursor at the end so the user can immediately
  // type additional fields without accidentally replacing existing ones.
  final hasExisting = existingDefs != null && existingDefs.isNotEmpty;
  String formatField(BitFieldDef field) => field.high == field.low
      ? '${field.name} ${field.high}'
      : '${field.name} ${field.high}:${field.low}';
  final initialText = hasExisting
      ? '${existingDefs.map(formatField).join('\n')}\n'
      : 'field0 $maxBit:0';

  final controller = TextEditingController(text: initialText);
  if (hasExisting) {
    // Cursor at the end (after trailing newline) — ready for a new field.
    controller.selection = TextSelection.collapsed(
      offset: controller.text.length,
    );
  } else {
    // First time: select all default text for easy replacement.
    controller.selection = TextSelection(
      baseOffset: 0,
      extentOffset: controller.text.length,
    );
  }

  final result = await showDialog<String>(
    context: context,
    barrierColor: Colors.black26,
    builder: (ctx) => AlertDialog(
      title: Text(
        '$signalName  [$width bits] — Define Fields',
        style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
      ),
      content: SizedBox(
        width: 320,
        child: TextField(
          controller: controller,
          autofocus: true,
          maxLines: 8,
          minLines: 3,
          style: const TextStyle(fontFamily: 'monospace', fontSize: 13),
          decoration: InputDecoration(
            labelText: 'One field per line: name high:low',
            hintText: 'exponent $maxBit:${maxBit - 10}\n'
                'mantissa ${maxBit - 11}:0',
            isDense: true,
            border: const OutlineInputBorder(),
          ),
        ),
      ),
      actions: [
        TextButton(
          onPressed: () => Navigator.of(ctx).pop(),
          child: const Text('Cancel'),
        ),
        TextButton(
          onPressed: () => Navigator.of(ctx).pop(controller.text),
          child: const Text('OK'),
        ),
      ],
    ),
  );

  if (result == null || result.trim().isEmpty) {
    return null;
  }
  final fields = BitFieldUtils.parseBitFieldDefs(result, maxBit);
  return fields.isEmpty ? null : fields;
}