Skip to content

Commit 8eea4f1

Browse files
Implementing switch expressions in widgets/ (#143293)
This PR is the 7�ʰ 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) This pull request covers everything in `packages/flutter/lib/src/widgets/`. Most of it should be really straightforward, but there was some refactoring in the `getOffsetToReveal()` function in `two_dimensional_viewport.dart`. I'll add some comments to describe those changes.
1 parent e94e406 commit 8eea4f1

19 files changed

+169
-306
lines changed

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

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,12 +1244,10 @@ class _FocusableActionDetectorState extends State<FocusableActionDetector> {
12441244
bool _canShowHighlight = false;
12451245
void _updateHighlightMode(FocusHighlightMode mode) {
12461246
_mayTriggerCallback(task: () {
1247-
switch (FocusManager.instance.highlightMode) {
1248-
case FocusHighlightMode.touch:
1249-
_canShowHighlight = false;
1250-
case FocusHighlightMode.traditional:
1251-
_canShowHighlight = true;
1252-
}
1247+
_canShowHighlight = switch (FocusManager.instance.highlightMode) {
1248+
FocusHighlightMode.touch => false,
1249+
FocusHighlightMode.traditional => true,
1250+
};
12531251
});
12541252
}
12551253

@@ -1303,13 +1301,10 @@ class _FocusableActionDetectorState extends State<FocusableActionDetector> {
13031301
}
13041302

13051303
bool canRequestFocus(FocusableActionDetector target) {
1306-
final NavigationMode mode = MediaQuery.maybeNavigationModeOf(context) ?? NavigationMode.traditional;
1307-
switch (mode) {
1308-
case NavigationMode.traditional:
1309-
return target.enabled;
1310-
case NavigationMode.directional:
1311-
return true;
1312-
}
1304+
return switch (MediaQuery.maybeNavigationModeOf(context)) {
1305+
NavigationMode.traditional || null => target.enabled,
1306+
NavigationMode.directional => true,
1307+
};
13131308
}
13141309

13151310
bool shouldShowFocusHighlight(FocusableActionDetector target) {
@@ -1344,13 +1339,10 @@ class _FocusableActionDetectorState extends State<FocusableActionDetector> {
13441339
}
13451340

13461341
bool get _canRequestFocus {
1347-
final NavigationMode mode = MediaQuery.maybeNavigationModeOf(context) ?? NavigationMode.traditional;
1348-
switch (mode) {
1349-
case NavigationMode.traditional:
1350-
return widget.enabled;
1351-
case NavigationMode.directional:
1352-
return true;
1353-
}
1342+
return switch (MediaQuery.maybeNavigationModeOf(context)) {
1343+
NavigationMode.traditional || null => widget.enabled,
1344+
NavigationMode.directional => true,
1345+
};
13541346
}
13551347

13561348
// This global key is needed to keep only the necessary widgets in the tree

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

Lines changed: 20 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -178,64 +178,32 @@ class BannerPainter extends CustomPainter {
178178
bool hitTest(Offset position) => false;
179179

180180
double _translationX(double width) {
181-
switch (layoutDirection) {
182-
case TextDirection.rtl:
183-
switch (location) {
184-
case BannerLocation.bottomEnd:
185-
return _kBottomOffset;
186-
case BannerLocation.topEnd:
187-
return 0.0;
188-
case BannerLocation.bottomStart:
189-
return width - _kBottomOffset;
190-
case BannerLocation.topStart:
191-
return width;
192-
}
193-
case TextDirection.ltr:
194-
switch (location) {
195-
case BannerLocation.bottomEnd:
196-
return width - _kBottomOffset;
197-
case BannerLocation.topEnd:
198-
return width;
199-
case BannerLocation.bottomStart:
200-
return _kBottomOffset;
201-
case BannerLocation.topStart:
202-
return 0.0;
203-
}
204-
}
181+
return switch ((layoutDirection, location)) {
182+
(TextDirection.rtl, BannerLocation.topStart) => width,
183+
(TextDirection.ltr, BannerLocation.topStart) => 0.0,
184+
(TextDirection.rtl, BannerLocation.topEnd) => 0.0,
185+
(TextDirection.ltr, BannerLocation.topEnd) => width,
186+
(TextDirection.rtl, BannerLocation.bottomStart) => width - _kBottomOffset,
187+
(TextDirection.ltr, BannerLocation.bottomStart) => _kBottomOffset,
188+
(TextDirection.rtl, BannerLocation.bottomEnd) => _kBottomOffset,
189+
(TextDirection.ltr, BannerLocation.bottomEnd) => width - _kBottomOffset,
190+
};
205191
}
206192

207193
double _translationY(double height) {
208-
switch (location) {
209-
case BannerLocation.bottomStart:
210-
case BannerLocation.bottomEnd:
211-
return height - _kBottomOffset;
212-
case BannerLocation.topStart:
213-
case BannerLocation.topEnd:
214-
return 0.0;
215-
}
194+
return switch (location) {
195+
BannerLocation.bottomStart || BannerLocation.bottomEnd => height - _kBottomOffset,
196+
BannerLocation.topStart || BannerLocation.topEnd => 0.0,
197+
};
216198
}
217199

218200
double get _rotation {
219-
switch (layoutDirection) {
220-
case TextDirection.rtl:
221-
switch (location) {
222-
case BannerLocation.bottomStart:
223-
case BannerLocation.topEnd:
224-
return -math.pi / 4.0;
225-
case BannerLocation.bottomEnd:
226-
case BannerLocation.topStart:
227-
return math.pi / 4.0;
228-
}
229-
case TextDirection.ltr:
230-
switch (location) {
231-
case BannerLocation.bottomStart:
232-
case BannerLocation.topEnd:
233-
return math.pi / 4.0;
234-
case BannerLocation.bottomEnd:
235-
case BannerLocation.topStart:
236-
return -math.pi / 4.0;
237-
}
238-
}
201+
return math.pi / 4.0 * switch ((layoutDirection, location)) {
202+
(TextDirection.rtl, BannerLocation.topStart || BannerLocation.bottomEnd) => 1,
203+
(TextDirection.ltr, BannerLocation.topStart || BannerLocation.bottomEnd) => -1,
204+
(TextDirection.rtl, BannerLocation.bottomStart || BannerLocation.topEnd) => -1,
205+
(TextDirection.ltr, BannerLocation.bottomStart || BannerLocation.topEnd) => 1,
206+
};
239207
}
240208
}
241209

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

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2813,16 +2813,11 @@ class UnconstrainedBox extends StatelessWidget {
28132813
final Widget? child;
28142814

28152815
BoxConstraintsTransform _axisToTransform(Axis? constrainedAxis) {
2816-
if (constrainedAxis != null) {
2817-
switch (constrainedAxis) {
2818-
case Axis.horizontal:
2819-
return ConstraintsTransformBox.heightUnconstrained;
2820-
case Axis.vertical:
2821-
return ConstraintsTransformBox.widthUnconstrained;
2822-
}
2823-
} else {
2824-
return ConstraintsTransformBox.unconstrained;
2825-
}
2816+
return switch (constrainedAxis) {
2817+
Axis.horizontal => ConstraintsTransformBox.heightUnconstrained,
2818+
Axis.vertical => ConstraintsTransformBox.widthUnconstrained,
2819+
null => ConstraintsTransformBox.unconstrained,
2820+
};
28262821
}
28272822

28282823
@override
@@ -4263,16 +4258,10 @@ class Positioned extends ParentDataWidget<StackParentData> {
42634258
double? height,
42644259
required Widget child,
42654260
}) {
4266-
double? left;
4267-
double? right;
4268-
switch (textDirection) {
4269-
case TextDirection.rtl:
4270-
left = end;
4271-
right = start;
4272-
case TextDirection.ltr:
4273-
left = start;
4274-
right = end;
4275-
}
4261+
final (double? left, double? right) = switch (textDirection) {
4262+
TextDirection.rtl => (end, start),
4263+
TextDirection.ltr => (start, end),
4264+
};
42764265
return Positioned(
42774266
key: key,
42784267
left: left,

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

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -785,15 +785,12 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
785785
}
786786

787787
Future<dynamic> _handleNavigationInvocation(MethodCall methodCall) {
788-
switch (methodCall.method) {
789-
case 'popRoute':
790-
return handlePopRoute();
791-
case 'pushRoute':
792-
return handlePushRoute(methodCall.arguments as String);
793-
case 'pushRouteInformation':
794-
return _handlePushRouteInformation(methodCall.arguments as Map<dynamic, dynamic>);
795-
}
796-
return Future<dynamic>.value();
788+
return switch (methodCall.method) {
789+
'popRoute' => handlePopRoute(),
790+
'pushRoute' => handlePushRoute(methodCall.arguments as String),
791+
'pushRouteInformation' => _handlePushRouteInformation(methodCall.arguments as Map<dynamic, dynamic>),
792+
_ => Future<dynamic>.value(),
793+
};
797794
}
798795

799796
@override

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

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,10 @@ class DecoratedBox extends SingleChildRenderObjectWidget {
9292
@override
9393
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
9494
super.debugFillProperties(properties);
95-
final String label;
96-
switch (position) {
97-
case DecorationPosition.background:
98-
label = 'bg';
99-
case DecorationPosition.foreground:
100-
label = 'fg';
101-
}
95+
final String label = switch (position) {
96+
DecorationPosition.background => 'bg',
97+
DecorationPosition.foreground => 'fg',
98+
};
10299
properties.add(EnumProperty<DecorationPosition>('position', position, level: DiagnosticLevel.hidden));
103100
properties.add(DiagnosticsProperty<Decoration>(label, decoration));
104101
}

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

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,10 @@ class DecoratedSliver extends SingleChildRenderObjectWidget {
7676
@override
7777
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
7878
super.debugFillProperties(properties);
79-
final String label;
80-
switch (position) {
81-
case DecorationPosition.background:
82-
label = 'bg';
83-
case DecorationPosition.foreground:
84-
label = 'fg';
85-
}
79+
final String label = switch (position) {
80+
DecorationPosition.background => 'bg',
81+
DecorationPosition.foreground => 'fg',
82+
};
8683
properties.add(EnumProperty<DecorationPosition>('position', position, level: DiagnosticLevel.hidden));
8784
properties.add(DiagnosticsProperty<Decoration>(label, decoration));
8885
}

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

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -472,20 +472,14 @@ class DefaultTextEditingShortcuts extends StatelessWidget {
472472
};
473473

474474
static Map<ShortcutActivator, Intent> get _shortcuts {
475-
switch (defaultTargetPlatform) {
476-
case TargetPlatform.android:
477-
return _androidShortcuts;
478-
case TargetPlatform.fuchsia:
479-
return _fuchsiaShortcuts;
480-
case TargetPlatform.iOS:
481-
return _iOSShortcuts;
482-
case TargetPlatform.linux:
483-
return _linuxShortcuts;
484-
case TargetPlatform.macOS:
485-
return _macShortcuts;
486-
case TargetPlatform.windows:
487-
return _windowsShortcuts;
488-
}
475+
return switch (defaultTargetPlatform) {
476+
TargetPlatform.android => _androidShortcuts,
477+
TargetPlatform.fuchsia => _fuchsiaShortcuts,
478+
TargetPlatform.iOS => _iOSShortcuts,
479+
TargetPlatform.linux => _linuxShortcuts,
480+
TargetPlatform.macOS => _macShortcuts,
481+
TargetPlatform.windows => _windowsShortcuts,
482+
};
489483
}
490484

491485
Map<ShortcutActivator, Intent>? _getDisablingShortcut() {

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -341,12 +341,11 @@ class _DismissibleState extends State<Dismissible> with TickerProviderStateMixin
341341
return DismissDirection.none;
342342
}
343343
if (_directionIsXAxis) {
344-
switch (Directionality.of(context)) {
345-
case TextDirection.rtl:
346-
return extent < 0 ? DismissDirection.startToEnd : DismissDirection.endToStart;
347-
case TextDirection.ltr:
348-
return extent > 0 ? DismissDirection.startToEnd : DismissDirection.endToStart;
349-
}
344+
return switch (Directionality.of(context)) {
345+
TextDirection.rtl when extent < 0 => DismissDirection.startToEnd,
346+
TextDirection.ltr when extent > 0 => DismissDirection.startToEnd,
347+
TextDirection.rtl || TextDirection.ltr => DismissDirection.endToStart,
348+
};
350349
}
351350
return extent > 0 ? DismissDirection.down : DismissDirection.up;
352351
}

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

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,10 @@ class DisplayFeatureSubScreen extends StatelessWidget {
114114
}
115115

116116
static Offset _fallbackAnchorPoint(BuildContext context) {
117-
final TextDirection textDirection = Directionality.of(context);
118-
switch (textDirection) {
119-
case TextDirection.rtl:
120-
return const Offset(double.maxFinite, 0);
121-
case TextDirection.ltr:
122-
return Offset.zero;
123-
}
117+
return switch (Directionality.of(context)) {
118+
TextDirection.rtl => const Offset(double.maxFinite, 0),
119+
TextDirection.ltr => Offset.zero,
120+
};
124121
}
125122

126123
/// Returns the areas of the screen that are obstructed by display features.

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

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -109,26 +109,20 @@ class _ToolbarLayout extends MultiChildLayoutDelegate {
109109
maxHeight: size.height,
110110
);
111111
leadingWidth = layoutChild(_ToolbarSlot.leading, constraints).width;
112-
final double leadingX;
113-
switch (textDirection) {
114-
case TextDirection.rtl:
115-
leadingX = size.width - leadingWidth;
116-
case TextDirection.ltr:
117-
leadingX = 0.0;
118-
}
112+
final double leadingX = switch (textDirection) {
113+
TextDirection.rtl => size.width - leadingWidth,
114+
TextDirection.ltr => 0.0,
115+
};
119116
positionChild(_ToolbarSlot.leading, Offset(leadingX, 0.0));
120117
}
121118

122119
if (hasChild(_ToolbarSlot.trailing)) {
123120
final BoxConstraints constraints = BoxConstraints.loose(size);
124121
final Size trailingSize = layoutChild(_ToolbarSlot.trailing, constraints);
125-
final double trailingX;
126-
switch (textDirection) {
127-
case TextDirection.rtl:
128-
trailingX = 0.0;
129-
case TextDirection.ltr:
130-
trailingX = size.width - trailingSize.width;
131-
}
122+
final double trailingX = switch (textDirection) {
123+
TextDirection.rtl => 0.0,
124+
TextDirection.ltr => size.width - trailingSize.width,
125+
};
132126
final double trailingY = (size.height - trailingSize.height) / 2.0;
133127
trailingWidth = trailingSize.width;
134128
positionChild(_ToolbarSlot.trailing, Offset(trailingX, trailingY));
@@ -153,13 +147,10 @@ class _ToolbarLayout extends MultiChildLayoutDelegate {
153147
}
154148
}
155149

156-
final double middleX;
157-
switch (textDirection) {
158-
case TextDirection.rtl:
159-
middleX = size.width - middleSize.width - middleStart;
160-
case TextDirection.ltr:
161-
middleX = middleStart;
162-
}
150+
final double middleX = switch (textDirection) {
151+
TextDirection.rtl => size.width - middleSize.width - middleStart,
152+
TextDirection.ltr => middleStart,
153+
};
163154

164155
positionChild(_ToolbarSlot.middle, Offset(middleX, middleY));
165156
}

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

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,17 +1686,11 @@ class SliverOverlapAbsorberHandle extends ChangeNotifier {
16861686

16871687
@override
16881688
String toString() {
1689-
String? extra;
1690-
switch (_writers) {
1691-
case 0:
1692-
extra = ', orphan';
1693-
case 1:
1694-
// normal case
1695-
break;
1696-
default:
1697-
extra = ', $_writers WRITERS ASSIGNED';
1698-
break;
1699-
}
1689+
final String? extra = switch (_writers) {
1690+
0 => ', orphan',
1691+
1 => null, // normal case
1692+
_ => ', $_writers WRITERS ASSIGNED',
1693+
};
17001694
return '${objectRuntimeType(this, 'SliverOverlapAbsorberHandle')}($layoutExtent$extra)';
17011695
}
17021696
}

0 commit comments

Comments
 (0)