Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement pressed state for MacosSwitch, MacosRadioButton, and MacosCheckbox #2

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,8 @@ MacosSwitch(
),
```

The `MacosSwitch` widget also has a pressed down state with a slight dimming effect and dark overlay while the mouse is pressed down.

Learn more about switches [here](https://developer.apple.com/design/human-interface-guidelines/toggles).

## MacosSegmentedControl
Expand Down
45 changes: 35 additions & 10 deletions lib/src/buttons/switch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ class _MacosSwitchState extends State<MacosSwitch>
// switch must be animated to the position indicated by the widget's value.
bool needsPositionAnimation = false;

@visibleForTesting
bool buttonHeldDown = false;

@override
void initState() {
super.initState();
Expand Down Expand Up @@ -208,6 +211,7 @@ class _MacosSwitchState extends State<MacosSwitch>
void _handleTapDown(TapDownDetails details) {
if (isInteractive) {
needsPositionAnimation = false;
setState(() => buttonHeldDown = true);
}
_reactionController.forward();
}
Expand All @@ -221,12 +225,14 @@ class _MacosSwitchState extends State<MacosSwitch>
void _handleTapUp(TapUpDetails details) {
if (isInteractive) {
needsPositionAnimation = false;
setState(() => buttonHeldDown = false);
_reactionController.reverse();
}
}

void _handleTapCancel() {
if (isInteractive) {
setState(() => buttonHeldDown = false);
_reactionController.reverse();
}
}
Expand Down Expand Up @@ -275,6 +281,20 @@ class _MacosSwitchState extends State<MacosSwitch>
super.dispose();
}

BoxDecoration _getClickEffectBoxDecoration() {
final MacosThemeData theme = MacosTheme.of(context);
final isDark = theme.brightness.isDark;

final color = isDark
? const MacosColor.fromRGBO(255, 255, 255, 0.15)
: const MacosColor.fromRGBO(0, 0, 0, 0.06);

return BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(20),
);
}

@override
Widget build(BuildContext context) {
assert(debugCheckHasMacosTheme(context));
Expand Down Expand Up @@ -307,16 +327,21 @@ class _MacosSwitchState extends State<MacosSwitch>
return Semantics(
label: widget.semanticLabel,
checked: widget.value,
child: _MacosSwitchRenderObjectWidget(
value: widget.value,
size: widget.size,
activeColor: activeColor,
trackColor: trackColor,
knobColor: knobColor,
borderColor: borderColor,
onChanged: widget.onChanged,
textDirection: Directionality.of(context),
state: this,
child: Container(
foregroundDecoration: buttonHeldDown
? _getClickEffectBoxDecoration()
: const BoxDecoration(),
child: _MacosSwitchRenderObjectWidget(
value: widget.value,
size: widget.size,
activeColor: activeColor,
trackColor: trackColor,
knobColor: knobColor,
borderColor: borderColor,
onChanged: widget.onChanged,
textDirection: Directionality.of(context),
state: this,
),
),
);
}
Expand Down
45 changes: 45 additions & 0 deletions test/buttons/checkbox_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,49 @@ void main() {
],
);
});

testWidgets('MacosCheckbox pressed down state', (tester) async {
bool? checked;
await tester.pumpWidget(
MacosApp(
home: MacosWindow(
child: MacosScaffold(
children: [
ContentArea(
builder: (context, _) {
return StatefulBuilder(
builder: (context, setState) {
return MacosCheckbox(
value: checked,
onChanged: (value) {
setState(() => checked = value);
},
);
},
);
},
),
],
),
),
),
);

final macosCheckbox = find.byType(MacosCheckbox);
expect(macosCheckbox, findsOneWidget);

final gesture = await tester.startGesture(tester.getCenter(macosCheckbox));
await tester.pump();
expect(
tester.widget<MacosCheckbox>(macosCheckbox).buttonHeldDown,
true,
);

await gesture.up();
await tester.pump();
expect(
tester.widget<MacosCheckbox>(macosCheckbox).buttonHeldDown,
false,
);
});
}
44 changes: 44 additions & 0 deletions test/buttons/radio_button_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,48 @@ void main() {
],
);
});

testWidgets('MacosRadioButton pressed down state', (tester) async {
TestOptions? selectedOption = TestOptions.first;
await tester.pumpWidget(
MacosApp(
home: MacosWindow(
child: MacosScaffold(
children: [
ContentArea(
builder: (context, _) {
return Center(
child: MacosRadioButton<TestOptions>(
value: TestOptions.first,
groupValue: selectedOption,
onChanged: (value) {
selectedOption = value;
},
),
);
},
),
],
),
),
),
);

final macosRadioButton = find.byType(MacosRadioButton<TestOptions>);
expect(macosRadioButton, findsOneWidget);

final gesture = await tester.startGesture(tester.getCenter(macosRadioButton));
await tester.pump();
expect(
tester.widget<MacosRadioButton<TestOptions>>(macosRadioButton).buttonHeldDown,
true,
);

await gesture.up();
await tester.pump();
expect(
tester.widget<MacosRadioButton<TestOptions>>(macosRadioButton).buttonHeldDown,
false,
);
});
}
43 changes: 43 additions & 0 deletions test/buttons/switch_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,47 @@ void main() {
],
);
});

testWidgets('MacosSwitch pressed down state', (tester) async {
bool selected = false;
await tester.pumpWidget(
MacosApp(
home: MacosWindow(
child: MacosScaffold(
children: [
ContentArea(
builder: (context, _) {
return Center(
child: MacosSwitch(
value: selected,
onChanged: (value) {
selected = value;
},
),
);
},
),
],
),
),
),
);

final macosSwitch = find.byType(MacosSwitch);
expect(macosSwitch, findsOneWidget);

final gesture = await tester.startGesture(tester.getCenter(macosSwitch));
await tester.pump();
expect(
tester.widget<MacosSwitch>(macosSwitch).buttonHeldDown,
true,
);

await gesture.up();
await tester.pump();
expect(
tester.widget<MacosSwitch>(macosSwitch).buttonHeldDown,
false,
);
});
}