Unverified Commit 5c6f65ee authored by Bruno Leroux's avatar Bruno Leroux Committed by GitHub

Add Tooltip onTriggered callback (#104237)

Co-authored-by: 's avatarBruno Leroux <bruno.leroux@gmail.com>
parent 4e4da19c
...@@ -16,6 +16,9 @@ import 'theme.dart'; ...@@ -16,6 +16,9 @@ import 'theme.dart';
import 'tooltip_theme.dart'; import 'tooltip_theme.dart';
import 'tooltip_visibility.dart'; import 'tooltip_visibility.dart';
/// Signature for when a tooltip is triggered.
typedef TooltipTriggeredCallback = void Function();
/// A Material Design tooltip. /// A Material Design tooltip.
/// ///
/// Tooltips provide text labels which help explain the function of a button or /// Tooltips provide text labels which help explain the function of a button or
...@@ -108,6 +111,7 @@ class Tooltip extends StatefulWidget { ...@@ -108,6 +111,7 @@ class Tooltip extends StatefulWidget {
this.showDuration, this.showDuration,
this.triggerMode, this.triggerMode,
this.enableFeedback, this.enableFeedback,
this.onTriggered,
this.child, this.child,
}) : assert((message == null) != (richMessage == null), 'Either `message` or `richMessage` must be specified'), }) : assert((message == null) != (richMessage == null), 'Either `message` or `richMessage` must be specified'),
assert( assert(
...@@ -238,6 +242,12 @@ class Tooltip extends StatefulWidget { ...@@ -238,6 +242,12 @@ class Tooltip extends StatefulWidget {
/// * [Feedback], for providing platform-specific feedback to certain actions. /// * [Feedback], for providing platform-specific feedback to certain actions.
final bool? enableFeedback; final bool? enableFeedback;
/// Called when the Tooltip is triggered.
///
/// The tooltip is triggered after a tap when [triggerMode] is [TooltipTriggerMode.tap]
/// or after a long press when [triggerMode] is [TooltipTriggerMode.longPress].
final TooltipTriggeredCallback? onTriggered;
static final List<TooltipState> _openedTooltips = <TooltipState>[]; static final List<TooltipState> _openedTooltips = <TooltipState>[];
// Causes any current tooltips to be concealed. Only called for mouse hover enter // Causes any current tooltips to be concealed. Only called for mouse hover enter
...@@ -661,6 +671,7 @@ class TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin { ...@@ -661,6 +671,7 @@ class TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
else else
Feedback.forTap(context); Feedback.forTap(context);
} }
widget.onTriggered?.call();
} }
@override @override
......
...@@ -1764,6 +1764,55 @@ void main() { ...@@ -1764,6 +1764,55 @@ void main() {
expect(find.text(tooltipText), findsNothing); expect(find.text(tooltipText), findsNothing);
}); });
testWidgets('Tooltip onTriggered is called when Tooltip triggers', (WidgetTester tester) async {
bool onTriggeredCalled = false;
void onTriggered() => onTriggeredCalled = true;
await setWidgetForTooltipMode(tester, TooltipTriggerMode.longPress, onTriggered: onTriggered);
Finder tooltip = find.byType(Tooltip);
await testGestureLongPress(tester, tooltip);
expect(onTriggeredCalled, true);
onTriggeredCalled = false;
await setWidgetForTooltipMode(tester, TooltipTriggerMode.tap, onTriggered: onTriggered);
tooltip = find.byType(Tooltip);
await testGestureTap(tester, tooltip);
expect(onTriggeredCalled, true);
});
testWidgets('Tooltip onTriggered is not called when Tooltip is hovered', (WidgetTester tester) async {
bool onTriggeredCalled = false;
void onTriggered() => onTriggeredCalled = true;
const Duration waitDuration = Duration.zero;
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
await gesture.addPointer();
await gesture.moveTo(Offset.zero);
await tester.pumpWidget(
MaterialApp(
home: Center(
child: Tooltip(
message: tooltipText,
waitDuration: waitDuration,
onTriggered: onTriggered,
child: const SizedBox(
width: 100.0,
height: 100.0,
),
),
),
),
);
final Finder tooltip = find.byType(Tooltip);
await gesture.moveTo(tester.getCenter(tooltip));
await tester.pump();
// Wait for it to appear.
await tester.pump(waitDuration);
expect(onTriggeredCalled, false);
});
testWidgets('Tooltip should not be shown with empty message (with child)', (WidgetTester tester) async { testWidgets('Tooltip should not be shown with empty message (with child)', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
...@@ -1791,12 +1840,13 @@ void main() { ...@@ -1791,12 +1840,13 @@ void main() {
}); });
} }
Future<void> setWidgetForTooltipMode(WidgetTester tester, TooltipTriggerMode triggerMode) async { Future<void> setWidgetForTooltipMode(WidgetTester tester, TooltipTriggerMode triggerMode, {TooltipTriggeredCallback? onTriggered}) async {
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
home: Tooltip( home: Tooltip(
message: tooltipText, message: tooltipText,
triggerMode: triggerMode, triggerMode: triggerMode,
onTriggered: onTriggered,
child: const SizedBox(width: 100.0, height: 100.0), child: const SizedBox(width: 100.0, height: 100.0),
), ),
), ),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment