Skip to content

Commit 93c4b09

Browse files
authored
Add RestorableEnumN<T> and RestorableEnum<T> to restorable primitive types (flutter#115050)
* Add RestorableEnumN and RestorableEnum to restorable primitive types * Review Changes * Change to assert if not part of the valid set. * Assert if default value isn't in the enum
1 parent 7d2b011 commit 93c4b09

File tree

2 files changed

+263
-0
lines changed

2 files changed

+263
-0
lines changed

packages/flutter/lib/src/widgets/restoration_properties.dart

+174
Original file line numberDiff line numberDiff line change
@@ -496,3 +496,177 @@ class RestorableTextEditingController extends RestorableChangeNotifier<TextEditi
496496
return value.text;
497497
}
498498
}
499+
500+
/// A [RestorableProperty] that knows how to store and restore a nullable [Enum]
501+
/// type.
502+
///
503+
/// {@macro flutter.widgets.RestorableNum}
504+
///
505+
/// The values are serialized using the name of the enum, obtained using the
506+
/// [EnumName.name] extension accessor.
507+
///
508+
/// The represented value is accessible via the [value] getter. The set of
509+
/// values in the enum are accessible via the [values] getter. Since
510+
/// [RestorableEnumN] allows null, this set will include null.
511+
///
512+
/// See also:
513+
///
514+
/// * [RestorableEnum], a class similar to this one that knows how to store and
515+
/// restore non-nullable [Enum] types.
516+
class RestorableEnumN<T extends Enum> extends RestorableValue<T?> {
517+
/// Creates a [RestorableEnumN].
518+
///
519+
/// {@macro flutter.widgets.RestorableNum.constructor}
520+
RestorableEnumN(T? defaultValue, { required Iterable<T> values })
521+
: assert(defaultValue == null || values.contains(defaultValue),
522+
'Default value $defaultValue not found in $T values: $values'),
523+
_defaultValue = defaultValue,
524+
values = values.toSet();
525+
526+
@override
527+
T? createDefaultValue() => _defaultValue;
528+
final T? _defaultValue;
529+
530+
@override
531+
set value(T? newValue) {
532+
assert(newValue == null || values.contains(newValue),
533+
'Attempted to set an unknown enum value "$newValue" that is not null, or '
534+
'in the valid set of enum values for the $T type: '
535+
'${values.map<String>((T value) => value.name).toSet()}');
536+
super.value = newValue;
537+
}
538+
539+
/// The set of non-null values that this [RestorableEnumN] may represent.
540+
///
541+
/// This is a required field that supplies the enum values that are serialized
542+
/// and restored.
543+
///
544+
/// If a value is encountered that is not null or a value in this set,
545+
/// [fromPrimitives] will assert when restoring.
546+
///
547+
/// It is typically set to the `values` list of the enum type.
548+
///
549+
/// In addition to this set, because [RestorableEnumN] allows nullable values,
550+
/// null is also a valid value, even though it doesn't appear in this set.
551+
///
552+
/// {@tool snippet} For example, to create a [RestorableEnumN] with an
553+
/// [AxisDirection] enum value, with a default value of null, you would build
554+
/// it like the code below:
555+
///
556+
/// ```dart
557+
/// RestorableEnumN<AxisDirection> axis = RestorableEnumN<AxisDirection>(null, values: AxisDirection.values);
558+
/// ```
559+
/// {@end-tool}
560+
Set<T> values;
561+
562+
@override
563+
void didUpdateValue(T? oldValue) {
564+
notifyListeners();
565+
}
566+
567+
@override
568+
T? fromPrimitives(Object? data) {
569+
if (data == null) {
570+
return null;
571+
}
572+
if (data is String) {
573+
for (final T allowed in values) {
574+
if (allowed.name == data) {
575+
return allowed;
576+
}
577+
}
578+
assert(false,
579+
'Attempted to set an unknown enum value "$data" that is not null, or '
580+
'in the valid set of enum values for the $T type: '
581+
'${values.map<String>((T value) => value.name).toSet()}');
582+
}
583+
return _defaultValue;
584+
}
585+
586+
@override
587+
Object? toPrimitives() => value?.name;
588+
}
589+
590+
591+
/// A [RestorableProperty] that knows how to store and restore an [Enum]
592+
/// type.
593+
///
594+
/// {@macro flutter.widgets.RestorableNum}
595+
///
596+
/// The values are serialized using the name of the enum, obtained using the
597+
/// [EnumName.name] extension accessor.
598+
///
599+
/// The represented value is accessible via the [value] getter.
600+
///
601+
/// See also:
602+
///
603+
/// * [RestorableEnumN], a class similar to this one that knows how to store and
604+
/// restore nullable [Enum] types.
605+
class RestorableEnum<T extends Enum> extends RestorableValue<T> {
606+
/// Creates a [RestorableEnum].
607+
///
608+
/// {@macro flutter.widgets.RestorableNum.constructor}
609+
RestorableEnum(T defaultValue, { required Iterable<T> values })
610+
: assert(values.contains(defaultValue),
611+
'Default value $defaultValue not found in $T values: $values'),
612+
_defaultValue = defaultValue,
613+
values = values.toSet();
614+
615+
@override
616+
T createDefaultValue() => _defaultValue;
617+
final T _defaultValue;
618+
619+
@override
620+
set value(T newValue) {
621+
assert(values.contains(newValue),
622+
'Attempted to set an unknown enum value "$newValue" that is not in the '
623+
'valid set of enum values for the $T type: '
624+
'${values.map<String>((T value) => value.name).toSet()}');
625+
626+
super.value = newValue;
627+
}
628+
629+
/// The set of values that this [RestorableEnum] may represent.
630+
///
631+
/// This is a required field that supplies the possible enum values that can
632+
/// be serialized and restored.
633+
///
634+
/// If a value is encountered that is not in this set, [fromPrimitives] will
635+
/// assert when restoring.
636+
///
637+
/// It is typically set to the `values` list of the enum type.
638+
///
639+
/// {@tool snippet} For example, to create a [RestorableEnum] with an
640+
/// [AxisDirection] enum value, with a default value of [AxisDirection.up],
641+
/// you would build it like the code below:
642+
///
643+
/// ```dart
644+
/// RestorableEnum<AxisDirection> axis = RestorableEnum<AxisDirection>(AxisDirection.up, values: AxisDirection.values);
645+
/// ```
646+
/// {@end-tool}
647+
Set<T> values;
648+
649+
@override
650+
void didUpdateValue(T? oldValue) {
651+
notifyListeners();
652+
}
653+
654+
@override
655+
T fromPrimitives(Object? data) {
656+
if (data != null && data is String) {
657+
for (final T allowed in values) {
658+
if (allowed.name == data) {
659+
return allowed;
660+
}
661+
}
662+
assert(false,
663+
'Attempted to restore an unknown enum value "$data" that is not in the '
664+
'valid set of enum values for the $T type: '
665+
'${values.map<String>((T value) => value.name).toSet()}');
666+
}
667+
return _defaultValue;
668+
}
669+
670+
@override
671+
Object toPrimitives() => value.name;
672+
}

0 commit comments

Comments
 (0)