Skip to content

Commit

Permalink
Implementing switch expressions: everything in flutter/lib/src/ (…
Browse files Browse the repository at this point in the history
…#143634)

This PR is the 9�ʰ step in the journey to solve issue #136139 and make the entire Flutter repo more readable.

(previous pull requests: #139048, #139882, #141591, #142279, #142634, #142793, #143293, #143496)

I did a pass through all of `packages/flutter/lib/src/` and found an abundance of `switch` statements to improve. Whereas #143496 focused on in-depth refactoring, this PR is full of simple, straightforward changes. (I ended up making some more complicated changes in `rendering/` and will file those separately after this PR is done.)
  • Loading branch information
nate-thegrate authored Feb 20, 2024
1 parent 3538e4c commit 7a4c246
Show file tree
Hide file tree
Showing 50 changed files with 503 additions and 925 deletions.
37 changes: 14 additions & 23 deletions packages/flutter/lib/src/animation/animation_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -598,20 +598,15 @@ class AnimationController extends Animation<double>
}

TickerFuture _animateToInternal(double target, { Duration? duration, Curve curve = Curves.linear }) {
double scale = 1.0;
if (SemanticsBinding.instance.disableAnimations) {
switch (animationBehavior) {
case AnimationBehavior.normal:
// Since the framework cannot handle zero duration animations, we run it at 5% of the normal
// duration to limit most animations to a single frame.
// Ideally, the framework would be able to handle zero duration animations, however, the common
// pattern of an eternally repeating animation might cause an endless loop if it weren't delayed
// for at least one frame.
scale = 0.05;
case AnimationBehavior.preserve:
break;
}
}
final double scale = switch (animationBehavior) {
// Since the framework cannot handle zero duration animations, we run it at 5% of the normal
// duration to limit most animations to a single frame.
// Ideally, the framework would be able to handle zero duration animations, however, the common
// pattern of an eternally repeating animation might cause an endless loop if it weren't delayed
// for at least one frame.
AnimationBehavior.normal when SemanticsBinding.instance.disableAnimations => 0.05,
AnimationBehavior.normal || AnimationBehavior.preserve => 1.0,
};
Duration? simulationDuration = duration;
if (simulationDuration == null) {
assert(!(this.duration == null && _direction == _AnimationDirection.forward));
Expand Down Expand Up @@ -721,16 +716,12 @@ class AnimationController extends Animation<double>
_direction = velocity < 0.0 ? _AnimationDirection.reverse : _AnimationDirection.forward;
final double target = velocity < 0.0 ? lowerBound - _kFlingTolerance.distance
: upperBound + _kFlingTolerance.distance;
double scale = 1.0;
final AnimationBehavior behavior = animationBehavior ?? this.animationBehavior;
if (SemanticsBinding.instance.disableAnimations) {
switch (behavior) {
case AnimationBehavior.normal:
scale = 200.0; // This is arbitrary (it was chosen because it worked for the drawer widget).
case AnimationBehavior.preserve:
break;
}
}
final double scale = switch (behavior) {
// This is arbitrary (it was chosen because it worked for the drawer widget).
AnimationBehavior.normal when SemanticsBinding.instance.disableAnimations => 200.0,
AnimationBehavior.normal || AnimationBehavior.preserve => 1.0,
};
final SpringSimulation simulation = SpringSimulation(springDescription, value, target, velocity * scale)
..tolerance = _kFlingTolerance;
assert(
Expand Down
23 changes: 8 additions & 15 deletions packages/flutter/lib/src/animation/animations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -425,15 +425,10 @@ class CurvedAnimation extends Animation<double> with AnimationWithParentMixin<do
bool isDisposed = false;

void _updateCurveDirection(AnimationStatus status) {
switch (status) {
case AnimationStatus.dismissed:
case AnimationStatus.completed:
_curveDirection = null;
case AnimationStatus.forward:
_curveDirection ??= AnimationStatus.forward;
case AnimationStatus.reverse:
_curveDirection ??= AnimationStatus.reverse;
}
_curveDirection = switch (status) {
AnimationStatus.dismissed || AnimationStatus.completed => null,
AnimationStatus.forward || AnimationStatus.reverse => _curveDirection ?? status,
};
}

bool get _useForwardCurve {
Expand Down Expand Up @@ -584,12 +579,10 @@ class TrainHoppingAnimation extends Animation<double>
bool hop = false;
if (_nextTrain != null) {
assert(_mode != null);
switch (_mode!) {
case _TrainHoppingMode.minimize:
hop = _nextTrain!.value <= _currentTrain!.value;
case _TrainHoppingMode.maximize:
hop = _nextTrain!.value >= _currentTrain!.value;
}
hop = switch (_mode!) {
_TrainHoppingMode.minimize => _nextTrain!.value <= _currentTrain!.value,
_TrainHoppingMode.maximize => _nextTrain!.value >= _currentTrain!.value,
};
if (hop) {
_currentTrain!
..removeStatusListener(_statusChangeHandler)
Expand Down
26 changes: 12 additions & 14 deletions packages/flutter/lib/src/cupertino/date_picker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -414,20 +414,18 @@ class CupertinoDatePicker extends StatefulWidget {
final double itemExtent;

@override
State<StatefulWidget> createState() { // ignore: no_logic_in_create_state, https://github.com/flutter/flutter/issues/70499
// The `time` mode and `dateAndTime` mode of the picker share the time
// columns, so they are placed together to one state.
// The `date` mode has different children and is implemented in a different
// state.
switch (mode) {
case CupertinoDatePickerMode.time:
case CupertinoDatePickerMode.dateAndTime:
return _CupertinoDatePickerDateTimeState();
case CupertinoDatePickerMode.date:
return _CupertinoDatePickerDateState(dateOrder: dateOrder);
case CupertinoDatePickerMode.monthYear:
return _CupertinoDatePickerMonthYearState(dateOrder: dateOrder);
}
State<StatefulWidget> createState() {
// ignore: no_logic_in_create_state, https://github.com/flutter/flutter/issues/70499
return switch (mode) {
// The `time` mode and `dateAndTime` mode of the picker share the time
// columns, so they are placed together to one state.
// The `date` mode has different children and is implemented in a different
// state.
CupertinoDatePickerMode.time => _CupertinoDatePickerDateTimeState(),
CupertinoDatePickerMode.dateAndTime => _CupertinoDatePickerDateTimeState(),
CupertinoDatePickerMode.date => _CupertinoDatePickerDateState(dateOrder: dateOrder),
CupertinoDatePickerMode.monthYear => _CupertinoDatePickerMonthYearState(dateOrder: dateOrder),
};
}

// Estimate the minimum width that each column needs to layout its content.
Expand Down
28 changes: 12 additions & 16 deletions packages/flutter/lib/src/cupertino/list_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -287,15 +287,12 @@ class _CupertinoListTileState extends State<CupertinoListTile> {
child: widget.title,
);

EdgeInsetsGeometry? padding = widget.padding;
if (padding == null) {
switch (widget._type) {
case _CupertinoListTileType.base:
padding = widget.subtitle == null ? _kPadding : _kPaddingWithSubtitle;
case _CupertinoListTileType.notched:
padding = widget.leading == null ? _kNotchedPaddingWithoutLeading : _kNotchedPadding;
}
}
final EdgeInsetsGeometry padding = widget.padding ?? switch (widget._type) {
_CupertinoListTileType.base when widget.subtitle != null => _kPaddingWithSubtitle,
_CupertinoListTileType.notched when widget.leading != null => _kNotchedPadding,
_CupertinoListTileType.base => _kPadding,
_CupertinoListTileType.notched => _kNotchedPaddingWithoutLeading,
};

Widget? subtitle;
if (widget.subtitle != null) {
Expand Down Expand Up @@ -325,13 +322,12 @@ class _CupertinoListTileState extends State<CupertinoListTile> {
backgroundColor = widget.backgroundColorActivated ?? CupertinoColors.systemGrey4.resolveFrom(context);
}

double minHeight;
switch (widget._type) {
case _CupertinoListTileType.base:
minHeight = subtitle == null ? _kMinHeight : _kMinHeightWithSubtitle;
case _CupertinoListTileType.notched:
minHeight = widget.leading == null ? _kNotchedMinHeightWithoutLeading : _kNotchedMinHeight;
}
final double minHeight = switch (widget._type) {
_CupertinoListTileType.base when subtitle != null => _kMinHeightWithSubtitle,
_CupertinoListTileType.notched when widget.leading != null => _kNotchedMinHeight,
_CupertinoListTileType.base => _kMinHeight,
_CupertinoListTileType.notched => _kNotchedMinHeightWithoutLeading,
};

final Widget child = Container(
constraints: BoxConstraints(minWidth: double.infinity, minHeight: minHeight),
Expand Down
14 changes: 4 additions & 10 deletions packages/flutter/lib/src/cupertino/route.dart
Original file line number Diff line number Diff line change
Expand Up @@ -975,16 +975,10 @@ class _CupertinoEdgeShadowPainter extends BoxPainter {

final TextDirection? textDirection = configuration.textDirection;
assert(textDirection != null);
final double start;
final double shadowDirection; // -1 for ltr, 1 for rtl.
switch (textDirection!) {
case TextDirection.rtl:
start = offset.dx + configuration.size!.width;
shadowDirection = 1;
case TextDirection.ltr:
start = offset.dx;
shadowDirection = -1;
}
final (double shadowDirection, double start) = switch (textDirection!) {
TextDirection.rtl => (1, offset.dx + configuration.size!.width),
TextDirection.ltr => (-1, offset.dx),
};

int bandColorIndex = 0;
for (int dx = 0; dx < shadowWidth; dx += 1) {
Expand Down
10 changes: 4 additions & 6 deletions packages/flutter/lib/src/cupertino/scrollbar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,10 @@ class _CupertinoScrollbarState extends RawScrollbarState<CupertinoScrollbar> {
if (direction == null) {
return;
}
switch (direction) {
case Axis.vertical:
_pressStartAxisPosition = localPosition.dy;
case Axis.horizontal:
_pressStartAxisPosition = localPosition.dx;
}
_pressStartAxisPosition = switch (direction) {
Axis.vertical => localPosition.dy,
Axis.horizontal => localPosition.dx,
};
}

@override
Expand Down
17 changes: 4 additions & 13 deletions packages/flutter/lib/src/cupertino/slider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -503,19 +503,10 @@ class _RenderCupertinoSlider extends RenderConstrainedBox implements MouseTracke

@override
void paint(PaintingContext context, Offset offset) {
final double visualPosition;
final Color leftColor;
final Color rightColor;
switch (textDirection) {
case TextDirection.rtl:
visualPosition = 1.0 - _position.value;
leftColor = _activeColor;
rightColor = trackColor;
case TextDirection.ltr:
visualPosition = _position.value;
leftColor = trackColor;
rightColor = _activeColor;
}
final (double visualPosition, Color leftColor, Color rightColor) = switch (textDirection) {
TextDirection.rtl => (1.0 - _position.value, _activeColor, trackColor),
TextDirection.ltr => (_position.value, trackColor, _activeColor),
};

final double trackCenter = offset.dy + size.height / 2.0;
final double trackLeft = offset.dx + _trackLeft;
Expand Down
10 changes: 4 additions & 6 deletions packages/flutter/lib/src/material/button_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -429,12 +429,10 @@ class _RenderButtonBarRow extends RenderFlex {
}
}
currentHeight += child.size.height;
switch (verticalDirection) {
case VerticalDirection.down:
child = childParentData.nextSibling;
case VerticalDirection.up:
child = childParentData.previousSibling;
}
child = switch (verticalDirection) {
VerticalDirection.down => childParentData.nextSibling,
VerticalDirection.up => childParentData.previousSibling,
};

if (overflowButtonSpacing != null && child != null) {
currentHeight += overflowButtonSpacing!;
Expand Down
20 changes: 5 additions & 15 deletions packages/flutter/lib/src/material/button_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -617,21 +617,11 @@ class ButtonThemeData with Diagnosticable {
/// [getTextTheme] is [ButtonTextTheme.primary], 16.0 on the left and right
/// otherwise.
EdgeInsetsGeometry getPadding(MaterialButton button) {
if (button.padding != null) {
return button.padding!;
}

if (_padding != null) {
return _padding;
}

switch (getTextTheme(button)) {
case ButtonTextTheme.normal:
case ButtonTextTheme.accent:
return const EdgeInsets.symmetric(horizontal: 16.0);
case ButtonTextTheme.primary:
return const EdgeInsets.symmetric(horizontal: 24.0);
}
return button.padding ?? _padding ?? switch (getTextTheme(button)) {
ButtonTextTheme.normal => const EdgeInsets.symmetric(horizontal: 16.0),
ButtonTextTheme.accent => const EdgeInsets.symmetric(horizontal: 16.0),
ButtonTextTheme.primary => const EdgeInsets.symmetric(horizontal: 24.0),
};
}

/// The shape of the [button]'s [Material].
Expand Down
13 changes: 5 additions & 8 deletions packages/flutter/lib/src/material/card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -213,14 +213,11 @@ class Card extends StatelessWidget {
final CardTheme cardTheme = CardTheme.of(context);
final CardTheme defaults;
if (Theme.of(context).useMaterial3) {
switch (_variant) {
case _CardVariant.elevated:
defaults = _CardDefaultsM3(context);
case _CardVariant.filled:
defaults = _FilledCardDefaultsM3(context);
case _CardVariant.outlined:
defaults = _OutlinedCardDefaultsM3(context);
}
defaults = switch (_variant) {
_CardVariant.elevated => _CardDefaultsM3(context),
_CardVariant.filled => _FilledCardDefaultsM3(context),
_CardVariant.outlined => _OutlinedCardDefaultsM3(context),
};
} else {
defaults = _CardDefaultsM2(context);
}
Expand Down
14 changes: 4 additions & 10 deletions packages/flutter/lib/src/material/checkbox_list_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -518,16 +518,10 @@ class CheckboxListTile extends StatelessWidget {
);
}

Widget? leading, trailing;
switch (controlAffinity) {
case ListTileControlAffinity.leading:
leading = control;
trailing = secondary;
case ListTileControlAffinity.trailing:
case ListTileControlAffinity.platform:
leading = secondary;
trailing = control;
}
final (Widget? leading, Widget? trailing) = switch (controlAffinity) {
ListTileControlAffinity.leading => (control, secondary),
ListTileControlAffinity.trailing || ListTileControlAffinity.platform => (secondary, control),
};
final ThemeData theme = Theme.of(context);
final CheckboxThemeData checkboxTheme = CheckboxTheme.of(context);
final Set<MaterialState> states = <MaterialState>{
Expand Down
35 changes: 12 additions & 23 deletions packages/flutter/lib/src/material/drawer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -646,35 +646,24 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro
}

AlignmentDirectional get _drawerOuterAlignment {
switch (widget.alignment) {
case DrawerAlignment.start:
return AlignmentDirectional.centerStart;
case DrawerAlignment.end:
return AlignmentDirectional.centerEnd;
}
return switch (widget.alignment) {
DrawerAlignment.start => AlignmentDirectional.centerStart,
DrawerAlignment.end => AlignmentDirectional.centerEnd,
};
}

AlignmentDirectional get _drawerInnerAlignment {
switch (widget.alignment) {
case DrawerAlignment.start:
return AlignmentDirectional.centerEnd;
case DrawerAlignment.end:
return AlignmentDirectional.centerStart;
}
return switch (widget.alignment) {
DrawerAlignment.start => AlignmentDirectional.centerEnd,
DrawerAlignment.end => AlignmentDirectional.centerStart,
};
}

Widget _buildDrawer(BuildContext context) {
final bool isDesktop;
switch (Theme.of(context).platform) {
case TargetPlatform.android:
case TargetPlatform.iOS:
case TargetPlatform.fuchsia:
isDesktop = false;
case TargetPlatform.macOS:
case TargetPlatform.linux:
case TargetPlatform.windows:
isDesktop = true;
}
final bool isDesktop = switch (Theme.of(context).platform) {
TargetPlatform.android || TargetPlatform.iOS || TargetPlatform.fuchsia => false,
TargetPlatform.macOS || TargetPlatform.linux || TargetPlatform.windows => true,
};

final double dragAreaWidth = widget.edgeDragWidth
?? _kEdgeDragWidth + switch ((widget.alignment, Directionality.of(context))) {
Expand Down
21 changes: 5 additions & 16 deletions packages/flutter/lib/src/material/dropdown_menu.dart
Original file line number Diff line number Diff line change
Expand Up @@ -484,22 +484,11 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
}

bool canRequestFocus() {
if (widget.focusNode != null) {
return widget.focusNode!.canRequestFocus;
}
if (widget.requestFocusOnTap != null) {
return widget.requestFocusOnTap!;
}
switch (Theme.of(context).platform) {
case TargetPlatform.iOS:
case TargetPlatform.android:
case TargetPlatform.fuchsia:
return false;
case TargetPlatform.macOS:
case TargetPlatform.linux:
case TargetPlatform.windows:
return true;
}
return widget.focusNode?.canRequestFocus ?? widget.requestFocusOnTap
?? switch (Theme.of(context).platform) {
TargetPlatform.iOS || TargetPlatform.android || TargetPlatform.fuchsia => false,
TargetPlatform.macOS || TargetPlatform.linux || TargetPlatform.windows => true,
};
}

void refreshLeadingPadding() {
Expand Down
Loading

0 comments on commit 7a4c246

Please sign in to comment.