anchor.diff:      _isRemoved = true;
     }
   }
  +
  +/// A hover card based tooltip.
  +class HoverCardTooltip extends StatefulWidget {
  +  const HoverCardTooltip({
  +    @required this.enabled,
  +    @required this.onHover,
  +    @required this.child,
  +    this.disposable,
  +  });
  +
  +  static const _hoverDelay = Duration(milliseconds: 500);
  +  static const defaultHoverWidth = 450.0;
  +
  +  /// Whether the tooltip is currently enabled.
  +  final bool Function() enabled;
  +
  +  /// Data to display when hovering over a particular point.
  +  final Future<HoverCardData> Function(PointerHoverEvent event) onHover;
  +
  +  final Widget child;
  +
  +  /// Disposable object to be disposed when the group is closed.
  +  final Disposable disposable;
  +
  +  @override
  +  _HoverCardTooltipState createState() => _HoverCardTooltipState();
  +}
  +
  +class _HoverCardTooltipState extends State<HoverCardTooltip> {
  +  /// A timer that shows a [HoverCard] with an evaluation result when completed.
  +  Timer _showTimer;
  +
  +  /// A timer that removes a [HoverCard] when completed.
  +  Timer _removeTimer;
  +
  +  /// Displays the evaluation result of a source code item.
  +  HoverCard _hoverCard;
  +
  +  void _onHoverExit() {
  +    _showTimer?.cancel();
  +    _removeTimer = Timer(HoverCardTooltip._hoverDelay, () {
  +      _hoverCard?.maybeRemove();
  +    });
  +  }
  +
  +  void _onHover(PointerHoverEvent event) {
  +    _showTimer?.cancel();
  +    _showTimer = null;
  +    _removeTimer?.cancel();
  +    _removeTimer = null;
  +
  +    if (!widget.enabled()) return;
  +    _showTimer = Timer(HoverCardTooltip._hoverDelay, () async {
  +      _hoverCard?.remove();
  +      _hoverCard = null;
  +      final hoverCardData = await widget.onHover(event);
  +      if (hoverCardData != null) {
  +        _hoverCard = HoverCard(
  +          context: context,
  +          event: event,
  +          title: hoverCardData.title,
  +          contents: hoverCardData.contents,
  +          width: hoverCardData.width,
  +        );
  +      }
  +    });
  +  }
  +
  +  @override
  +  void dispose() {
  +    _showTimer?.cancel();
  +    _removeTimer?.cancel();
  +    _hoverCard?.remove();
  +    widget.disposable?.dispose();
  +    super.dispose();
  +  }
  +
  +  @override
  +  Widget build(BuildContext context) {
  +    return MouseRegion(
  +      onExit: (_) => _onHoverExit(),
  +      onHover: _onHover,
  +      child: widget.child,
  +    );
  +  }
  +}
  
positive.code: 
      _overlayEntry = OverlayEntry(builder: (context) {
        return Positioned(
          left: position.dx - (width / 2.0),
          top: position.dy + _hoverYOffset,
          child: MouseRegion(
            onExit: (_) {
  
negative.code: const _hoverCardBorderWidth = 2.0;
  const _hoverYOffset = 10;
  
  class HoverCardData {
    HoverCardData({
      @required this.title,
      @required this.contents,
      this.width = HoverCardTooltip.defaultHoverWidth,
    });
  
    final String title;
    final Widget contents;
    final double width;
  }
  
  /// A card to display content while hovering over a widget.
  ///
  /// This widget will automatically remove itself after the mouse has entered
  