FormeListTile<T extends Object> constructor

FormeListTile<T extends Object>({
  1. Key? key,
  2. String? name,
  3. List<T> initialValue = const [],
  4. FormeAsyncValidator<List<T>>? asyncValidator,
  5. Duration? asyncValidatorDebounce,
  6. AutovalidateMode? autovalidateMode,
  7. bool enabled = true,
  8. FocusNode? focusNode,
  9. FormeFieldInitialized<List<T>>? onInitialized,
  10. FormeFieldSetter<List<T>>? onSaved,
  11. FormeFieldStatusChanged<List<T>>? onStatusChanged,
  12. int? order,
  13. bool quietlyValidate = false,
  14. bool readOnly = false,
  15. bool requestFocusOnUserInteraction = true,
  16. FormeFieldValidationFilter<List<T>>? validationFilter,
  17. FormeValidator<List<T>>? validator,
  18. FormeFieldDecorator<List<T>>? decorator,
  19. int? maxSelectedCount,
  20. WrapAlignment alignment = WrapAlignment.start,
  21. Clip? clipBehavior,
  22. EdgeInsetsGeometry? contentPadding,
  23. WrapCrossAlignment crossAxisAlignment = WrapCrossAlignment.start,
  24. InputDecoration? decoration,
  25. bool dense = true,
  26. Axis direction = Axis.horizontal,
  27. bool? enableFeedback,
  28. double? horizontalTitleGap,
  29. Color? iconColor,
  30. VoidCallback? maxSelectedExceedCallback,
  31. double? minLeadingWidth,
  32. double? minVerticalPadding,
  33. WrapAlignment runAlignment = WrapAlignment.start,
  34. double runSpacing = 0.0,
  35. Color? selectedColor,
  36. Color? selectedTileColor,
  37. ShapeBorder? shape,
  38. double spacing = 0.0,
  39. int split = 2,
  40. ListTileStyle? style,
  41. Color? textColor,
  42. TextDirection? textDirection,
  43. Color? tileColor,
  44. FormeListTileType type = FormeListTileType.checkbox,
  45. VerticalDirection verticalDirection = VerticalDirection.down,
  46. required List<FormeListTileItem<T>> items,
})

Implementation

FormeListTile({
  super.key,
  super.name,
  super.initialValue = const [],
  super.asyncValidator,
  super.asyncValidatorDebounce,
  super.autovalidateMode,
  super.enabled = true,
  super.focusNode,
  super.onInitialized,
  super.onSaved,
  super.onStatusChanged,
  super.order,
  super.quietlyValidate = false,
  super.readOnly = false,
  super.requestFocusOnUserInteraction = true,
  super.validationFilter,
  super.validator,
  FormeFieldDecorator<List<T>>? decorator,
  this.maxSelectedCount,
  this.alignment = WrapAlignment.start,
  this.clipBehavior,
  this.contentPadding,
  this.crossAxisAlignment = WrapCrossAlignment.start,
  this.decoration,
  this.dense = true,
  this.direction = Axis.horizontal,
  this.enableFeedback,
  this.horizontalTitleGap,
  this.iconColor,
  this.maxSelectedExceedCallback,
  this.minLeadingWidth,
  this.minVerticalPadding,
  this.runAlignment = WrapAlignment.start,
  this.runSpacing = 0.0,
  this.selectedColor,
  this.selectedTileColor,
  this.shape,
  this.spacing = 0.0,
  this.split = 2,
  this.style,
  this.textColor,
  this.textDirection,
  this.tileColor,
  this.type = FormeListTileType.checkbox,
  this.verticalDirection = VerticalDirection.down,
  required this.items,
}) : super.allFields(
          decorator: decorator ??
              (decoration == null
                  ? null
                  : FormeInputDecorationDecorator(
                      maxLength: maxSelectedCount,
                      decorationBuilder: (context) => decoration)),
          builder: (state) {
            final bool readOnly = state.readOnly;

            final List<Widget> wrapWidgets = [];

            void changeValue(T value) {
              final List<T> values = List.of(state.value);
              if (!values.remove(value)) {
                if (maxSelectedCount != null &&
                    values.length >= maxSelectedCount) {
                  if (maxSelectedExceedCallback != null) {
                    maxSelectedExceedCallback();
                  }
                  return;
                }
                values.add(value);
              }
              state.didChange(values);
              state.requestFocusOnUserInteraction();
            }

            Widget createFormeListTileItem(
                FormeListTileItem<T> item, bool selected, bool readOnly) {
              switch (type) {
                case FormeListTileType.checkbox:
                  return CheckboxListTile(
                    enableFeedback: item.enableFeedback,
                    visualDensity: item.visualDensity,
                    side: item.side,
                    tristate: false,
                    isThreeLine: item.isThreeLine ?? false,
                    shape: item.shape,
                    tileColor: item.tileColor,
                    selectedTileColor: item.selectedTileColor,
                    activeColor: item.activeColor,
                    checkColor: item.checkColor,
                    secondary: item.secondary,
                    subtitle: item.subtitle,
                    controlAffinity: item.controlAffinity,
                    contentPadding: item.padding,
                    dense: item.dense,
                    title: item.title,
                    checkboxShape: item.checkboxShape,
                    value: selected,
                    onChanged:
                        readOnly ? null : (v) => changeValue(item.data),
                  );
                case FormeListTileType.switchs:
                  return SwitchListTile(
                    enableFeedback: item.enableFeedback,
                    visualDensity: item.visualDensity,
                    isThreeLine: item.isThreeLine ?? false,
                    tileColor: item.tileColor,
                    activeColor: item.activeColor,
                    shape: item.shape,
                    selectedTileColor: item.selectedTileColor,
                    secondary: item.secondary,
                    subtitle: item.subtitle,
                    controlAffinity: item.controlAffinity,
                    contentPadding: item.padding,
                    dense: item.dense,
                    title: item.title,
                    hoverColor: item.hoverColor,
                    activeTrackColor: item.activeTrackColor,
                    inactiveThumbColor: item.inactiveThumbColor,
                    inactiveTrackColor: item.inactiveTrackColor,
                    activeThumbImage: item.activeThumbImage,
                    inactiveThumbImage: item.inactiveThumbImage,
                    value: selected,
                    onChanged:
                        readOnly ? null : (v) => changeValue(item.data),
                  );
              }
            }

            Widget createCommonItem(
                FormeListTileItem<T> item, bool selected, bool readOnly) {
              switch (type) {
                case FormeListTileType.checkbox:
                  return Checkbox(
                    tristate: false,
                    side: item.side,
                    activeColor: item.activeColor,
                    checkColor: item.checkColor,
                    mouseCursor: item.mouseCursor,
                    shape: item.checkboxShape,
                    fillColor: item.fillColor,
                    materialTapTargetSize: item.materialTapTargetSize,
                    focusColor: item.focusColor,
                    hoverColor: item.hoverColor,
                    overlayColor: item.overlayColor,
                    splashRadius: item.splashRadius,
                    visualDensity: item.visualDensity,
                    value: selected,
                    onChanged: readOnly || item.readOnly
                        ? null
                        : (v) => changeValue(item.data),
                  );
                case FormeListTileType.switchs:
                  return Switch(
                    value: selected,
                    onChanged: readOnly || item.readOnly
                        ? null
                        : (v) => changeValue(item.data),
                    activeColor: item.activeColor,
                    activeTrackColor: item.activeTrackColor,
                    inactiveThumbColor: item.inactiveThumbColor,
                    inactiveTrackColor: item.inactiveTrackColor,
                    activeThumbImage: item.activeThumbImage,
                    inactiveThumbImage: item.inactiveThumbImage,
                    materialTapTargetSize: item.materialTapTargetSize,
                    focusColor: item.focusColor,
                    hoverColor: item.hoverColor,
                    overlayColor: item.overlayColor,
                    splashRadius: item.splashRadius,
                    thumbColor: item.thumbColor,
                    trackColor: item.trackColor,
                    dragStartBehavior:
                        item.dragStartBehavior ?? DragStartBehavior.start,
                    onActiveThumbImageError: item.onActiveThumbImageError,
                    onInactiveThumbImageError: item.onInactiveThumbImageError,
                    thumbIcon: item.thumbIcon,
                    mouseCursor: item.mouseCursor,
                  );
              }
            }

            for (int i = 0; i < items.length; i++) {
              final FormeListTileItem<T> item = items[i];
              final bool isReadOnly = readOnly || item.readOnly;
              final bool selected = state.value.contains(item.data);
              if (split > 0) {
                final double factor = 1 / split;
                if (factor == 1) {
                  wrapWidgets.add(
                      createFormeListTileItem(item, selected, isReadOnly));
                  continue;
                }
              }

              final Widget tileItem =
                  createCommonItem(item, selected, readOnly);

              final Widget title = split == 0
                  ? item.title
                  : Flexible(
                      child: item.title,
                    );

              List<Widget> children;
              switch (item.controlAffinity) {
                case ListTileControlAffinity.leading:
                  children = [tileItem, title];
                  break;
                default:
                  children = [title, tileItem];
                  break;
              }

              final Row tileItemRow = Row(
                mainAxisSize: MainAxisSize.min,
                children: children,
              );

              final Widget groupItemWidget = Padding(
                padding: item.padding,
                child: InkWell(
                    borderRadius:
                        const BorderRadius.all(Radius.circular(4.0)),
                    onTap: isReadOnly
                        ? null
                        : () {
                            changeValue(item.data);
                          },
                    child: tileItemRow),
              );

              final bool visible = item.visible;
              if (split <= 0) {
                wrapWidgets.add(Visibility(
                  visible: visible,
                  child: groupItemWidget,
                ));
                if (visible && i < items.length - 1) {
                  wrapWidgets.add(const SizedBox(
                    width: 8.0,
                  ));
                }
              } else {
                final double factor = item.ignoreSplit ? 1 : 1 / split;
                wrapWidgets.add(Visibility(
                  visible: visible,
                  child: FractionallySizedBox(
                    widthFactor: factor,
                    child: groupItemWidget,
                  ),
                ));
              }
            }
            Widget child = Wrap(
              spacing: spacing,
              runSpacing: runSpacing,
              textDirection: textDirection,
              crossAxisAlignment: crossAxisAlignment,
              verticalDirection: verticalDirection,
              alignment: alignment,
              direction: direction,
              runAlignment: runAlignment,
              clipBehavior: clipBehavior ?? Clip.none,
              children: wrapWidgets,
            );
            if (split == 1) {
              child = ListTileTheme.merge(
                child: child,
                dense: dense,
                shape: shape,
                style: style,
                selectedColor: selectedColor,
                iconColor: iconColor,
                textColor: textColor,
                contentPadding: contentPadding,
                tileColor: tileColor,
                selectedTileColor: selectedTileColor,
                enableFeedback: enableFeedback,
                horizontalTitleGap: horizontalTitleGap,
                minVerticalPadding: minVerticalPadding,
                minLeadingWidth: minLeadingWidth,
              );
            }

            return Focus(
              focusNode: state.focusNode,
              child: child,
            );
          });