Unverified Commit 63a64a88 authored by Markus Aksli's avatar Markus Aksli Committed by GitHub

Revert "Add `TooltipVisibility` widget (#91609)" (#92088)

This reverts commit 6b94f2f6.
parent 6b94f2f6
......@@ -158,7 +158,6 @@ export 'src/material/toggle_buttons_theme.dart';
export 'src/material/toggleable.dart';
export 'src/material/tooltip.dart';
export 'src/material/tooltip_theme.dart';
export 'src/material/tooltip_visibility.dart';
export 'src/material/typography.dart';
export 'src/material/user_accounts_drawer_header.dart';
export 'widgets.dart';
......@@ -14,7 +14,6 @@ import 'colors.dart';
import 'feedback.dart';
import 'theme.dart';
import 'tooltip_theme.dart';
import 'tooltip_visibility.dart';
/// A material design tooltip.
///
......@@ -70,7 +69,6 @@ import 'tooltip_visibility.dart';
///
/// * <https://material.io/design/components/tooltips.html>
/// * [TooltipTheme] or [ThemeData.tooltipTheme]
/// * [TooltipVisibility]
class Tooltip extends StatefulWidget {
/// Creates a tooltip.
///
......@@ -329,7 +327,6 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
late bool enableFeedback;
late bool _isConcealed;
late bool _forceRemoval;
late bool _visible;
/// The plain text message for this tooltip.
///
......@@ -355,12 +352,6 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
GestureBinding.instance!.pointerRouter.addGlobalRoute(_handlePointerEvent);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
_visible = TooltipVisibility.of(context);
}
// https://material.io/components/tooltips#specs
double _getDefaultTooltipHeight() {
final ThemeData theme = Theme.of(context);
......@@ -492,11 +483,8 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
/// Shows the tooltip if it is not already visible.
///
/// Returns `false` when the tooltip shouldn't be shown or when the tooltip
/// was already visible.
/// Returns `false` when the tooltip was already visible.
bool ensureTooltipVisible() {
if (!_visible)
return false;
_showTimer?.cancel();
_showTimer = null;
_forceRemoval = false;
......@@ -683,31 +671,27 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
triggerMode = widget.triggerMode ?? tooltipTheme.triggerMode ?? _defaultTriggerMode;
enableFeedback = widget.enableFeedback ?? tooltipTheme.enableFeedback ?? _defaultEnableFeedback;
Widget result = Semantics(
label: excludeFromSemantics
? null
: _tooltipMessage,
child: widget.child,
Widget result = GestureDetector(
behavior: HitTestBehavior.opaque,
onLongPress: (triggerMode == TooltipTriggerMode.longPress) ?
_handlePress : null,
onTap: (triggerMode == TooltipTriggerMode.tap) ? _handlePress : null,
excludeFromSemantics: true,
child: Semantics(
label: excludeFromSemantics
? null
: _tooltipMessage,
child: widget.child,
),
);
// Only check for gestures if tooltip should be visible.
if (_visible) {
result = GestureDetector(
behavior: HitTestBehavior.opaque,
onLongPress: (triggerMode == TooltipTriggerMode.longPress) ?
_handlePress : null,
onTap: (triggerMode == TooltipTriggerMode.tap) ? _handlePress : null,
excludeFromSemantics: true,
// Only check for hovering if there is a mouse connected.
if (_mouseIsConnected) {
result = MouseRegion(
onEnter: (_) => _handleMouseEnter(),
onExit: (_) => _handleMouseExit(),
child: result,
);
// Only check for hovering if there is a mouse connected.
if (_mouseIsConnected) {
result = MouseRegion(
onEnter: (_) => _handleMouseEnter(),
onExit: (_) => _handleMouseExit(),
child: result,
);
}
}
return result;
......
......@@ -242,10 +242,6 @@ class TooltipThemeData with Diagnosticable {
/// )
/// ```
/// {@end-tool}
///
/// See also:
///
/// * [TooltipVisibility], which can be used to visually disable descendant [Tooltip]s.
class TooltipTheme extends InheritedTheme {
/// Creates a tooltip theme that controls the configurations for
/// [Tooltip].
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/widgets.dart';
class _TooltipVisibilityScope extends InheritedWidget {
const _TooltipVisibilityScope({
Key? key,
required Widget child,
required this.visible,
}) : super(key: key, child: child);
final bool visible;
@override
bool updateShouldNotify(_TooltipVisibilityScope old) {
return old.visible != visible;
}
}
/// Overrides the visibility of descendant [Tooltip] widgets.
///
/// If disabled, the descendant [Tooltip] widgets will not display a tooltip
/// when tapped, long-pressed, hovered by the mouse, or when
/// `ensureTooltipVisible` is called. This only visually disables tooltips but
/// continues to provide any semantic information that is provided.
class TooltipVisibility extends StatelessWidget {
/// Creates a widget that configures the visibility of [Tooltip].
///
/// Both arguments must not be null.
const TooltipVisibility({
Key? key,
required this.child,
required this.visible,
}) : super(key: key);
/// The widget below this widget in the tree.
///
/// The entire app can be wrapped in this widget to globally control [Tooltip]
/// visibility.
///
/// {@macro flutter.widgets.ProxyWidget.child}
final Widget child;
/// Determines the visibility of [Tooltip] widgets that inherit from this widget.
final bool visible;
/// The [visible] of the closest instance of this class that encloses the
/// given context. Defaults to `true` if none are found.
static bool of(BuildContext context) {
final _TooltipVisibilityScope? visibility = context.dependOnInheritedWidgetOfExactType<_TooltipVisibilityScope>();
return visibility?.visible ?? true;
}
@override
Widget build(BuildContext context) {
return _TooltipVisibilityScope(
child: child,
visible: visible,
);
}
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
void _ensureTooltipVisible(GlobalKey key) {
// This function uses "as dynamic" to defeat the static analysis. In general
// you want to avoid using this style in your code, as it will cause the
// analyzer to be unable to help you catch errors.
//
// In this case, we do it because we are trying to call internal methods of
// the tooltip code in order to test it. Normally, the state of a tooltip is a
// private class, but by using a GlobalKey we can get a handle to that object
// and by using "as dynamic" we can bypass the analyzer's type checks and call
// methods that we aren't supposed to be able to know about.
//
// It's ok to do this in tests, but you really don't want to do it in
// production code.
// ignore: avoid_dynamic_calls
(key.currentState as dynamic).ensureTooltipVisible();
}
const String tooltipText = 'TIP';
void main() {
testWidgets('Tooltip does not build MouseRegion when mouse is detected and in TooltipVisibility with visibility = false', (WidgetTester tester) async {
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
addTearDown(() async {
if (gesture != null)
return gesture.removePointer();
});
await gesture.addPointer();
await gesture.moveTo(const Offset(1.0, 1.0));
await tester.pump();
await gesture.moveTo(Offset.zero);
await tester.pumpWidget(
const MaterialApp(
home: TooltipVisibility(
visible: false,
child: Tooltip(
message: tooltipText,
child: SizedBox(
width: 100.0,
height: 100.0,
),
),
),
),
);
expect(find.descendant(of: find.byType(Tooltip), matching: find.byType(MouseRegion)), findsNothing);
});
testWidgets('Tooltip does not show when hovered when in TooltipVisibility with visible = false', (WidgetTester tester) async {
const Duration waitDuration = Duration.zero;
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
addTearDown(() async {
if (gesture != null)
return gesture.removePointer();
});
await gesture.addPointer();
await gesture.moveTo(const Offset(1.0, 1.0));
await tester.pump();
await gesture.moveTo(Offset.zero);
await tester.pumpWidget(
const MaterialApp(
home: Center(
child: TooltipVisibility(
visible: false,
child: Tooltip(
message: tooltipText,
waitDuration: waitDuration,
child: SizedBox(
width: 100.0,
height: 100.0,
),
),
),
),
),
);
final Finder tooltip = find.byType(Tooltip);
await gesture.moveTo(Offset.zero);
await tester.pump();
await gesture.moveTo(tester.getCenter(tooltip));
await tester.pump();
// Wait for it to appear.
await tester.pump(waitDuration);
expect(find.text(tooltipText), findsNothing);
});
testWidgets('Tooltip shows when hovered when in TooltipVisibility with visible = true', (WidgetTester tester) async {
const Duration waitDuration = Duration.zero;
TestGesture? gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
addTearDown(() async {
if (gesture != null)
return gesture.removePointer();
});
await gesture.addPointer();
await gesture.moveTo(const Offset(1.0, 1.0));
await tester.pump();
await gesture.moveTo(Offset.zero);
await tester.pumpWidget(
const MaterialApp(
home: Center(
child: TooltipVisibility(
visible: true,
child: Tooltip(
message: tooltipText,
waitDuration: waitDuration,
child: SizedBox(
width: 100.0,
height: 100.0,
),
),
),
),
),
);
final Finder tooltip = find.byType(Tooltip);
await gesture.moveTo(Offset.zero);
await tester.pump();
await gesture.moveTo(tester.getCenter(tooltip));
await tester.pump();
// Wait for it to appear.
await tester.pump(waitDuration);
expect(find.text(tooltipText), findsOneWidget);
// Wait for it to disappear.
await gesture.moveTo(Offset.zero);
await tester.pumpAndSettle();
await gesture.removePointer();
gesture = null;
expect(find.text(tooltipText), findsNothing);
});
testWidgets('Tooltip does not build GestureDetector when in TooltipVisibility with visibility = false', (WidgetTester tester) async {
await setWidgetForTooltipMode(tester, TooltipTriggerMode.tap, false);
expect(find.byType(GestureDetector), findsNothing);
});
testWidgets('Tooltip triggers on tap when trigger mode is tap and in TooltipVisibility with visible = true', (WidgetTester tester) async {
await setWidgetForTooltipMode(tester, TooltipTriggerMode.tap, true);
final Finder tooltip = find.byType(Tooltip);
expect(find.text(tooltipText), findsNothing);
await testGestureTap(tester, tooltip);
expect(find.text(tooltipText), findsOneWidget);
});
testWidgets('Tooltip does not trigger manually when in TooltipVisibility with visible = false', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpWidget(
MaterialApp(
home: TooltipVisibility(
visible: false,
child: Tooltip(
key: key,
message: tooltipText,
child: const SizedBox(width: 100.0, height: 100.0),
),
),
),
);
_ensureTooltipVisible(key);
await tester.pump();
expect(find.text(tooltipText), findsNothing);
});
testWidgets('Tooltip triggers manually when in TooltipVisibility with visible = true', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpWidget(
MaterialApp(
home: TooltipVisibility(
visible: true,
child: Tooltip(
key: key,
message: tooltipText,
child: const SizedBox(width: 100.0, height: 100.0),
),
),
),
);
_ensureTooltipVisible(key);
await tester.pump();
expect(find.text(tooltipText), findsOneWidget);
});
}
Future<void> setWidgetForTooltipMode(WidgetTester tester, TooltipTriggerMode triggerMode, bool visibility) async {
await tester.pumpWidget(
MaterialApp(
home: TooltipVisibility(
visible: visibility,
child: Tooltip(
message: tooltipText,
triggerMode: triggerMode,
child: const SizedBox(width: 100.0, height: 100.0),
),
),
),
);
}
Future<void> testGestureTap(WidgetTester tester, Finder tooltip) async {
await tester.tap(tooltip);
await tester.pump(const Duration(milliseconds: 10));
}
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