// 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.

// @dart = 2.8

import 'package:flutter/foundation.dart';

import 'basic.dart';
import 'focus_manager.dart';
import 'framework.dart';
import 'inherited_notifier.dart';

/// A widget that manages a [FocusNode] to allow keyboard focus to be given
/// to this widget and its descendants.
///
/// When the focus is gained or lost, [onFocusChange] is called.
///
/// For keyboard events, [onKey] is called if [FocusNode.hasFocus] is true for
/// this widget's [focusNode], unless a focused descendant's [onKey] callback
/// returns true when called.
///
/// This widget does not provide any visual indication that the focus has
/// changed. Any desired visual changes should be made when [onFocusChange] is
/// called.
///
/// To access the [FocusNode] of the nearest ancestor [Focus] widget and
/// establish a relationship that will rebuild the widget when the focus
/// changes, use the [Focus.of] and [FocusScope.of] static methods.
///
/// To access the focused state of the nearest [Focus] widget, use
/// [FocusNode.hasFocus] from a build method, which also establishes a relationship
/// between the calling widget and the [Focus] widget that will rebuild the
/// calling widget when the focus changes.
///
/// Managing a [FocusNode] means managing its lifecycle, listening for changes
/// in focus, and re-parenting it when needed to keep the focus hierarchy in
/// sync with the widget hierarchy. This widget does all of those things for
/// you. See [FocusNode] for more information about the details of what node
/// management entails if you are not using a [Focus] widget and you need to do
/// it yourself.
///
/// To collect a sub-tree of nodes into an exclusive group that restricts focus
/// traversal to the group, use a [FocusScope]. To collect a sub-tree of nodes
/// into a group that has a specific order to its traversal but allows the
/// traversal to escape the group, use a [FocusTraversalGroup].
///
/// To move the focus, use methods on [FocusNode] by getting the [FocusNode]
/// through the [of] method. For instance, to move the focus to the next node in
/// the focus traversal order, call `Focus.of(context).nextFocus()`. To unfocus
/// a widget, call `Focus.of(context).unfocus()`.
///
/// {@tool dartpad --template=stateful_widget_scaffold}
/// This example shows how to manage focus using the [Focus] and [FocusScope]
/// widgets. See [FocusNode] for a similar example that doesn't use [Focus] or
/// [FocusScope].
///
/// ```dart imports
/// import 'package:flutter/services.dart';
/// ```
///
/// ```dart
/// Color _color = Colors.white;
///
/// bool _handleKeyPress(FocusNode node, RawKeyEvent event) {
///   if (event is RawKeyDownEvent) {
///     print('Focus node ${node.debugLabel} got key event: ${event.logicalKey}');
///     if (event.logicalKey == LogicalKeyboardKey.keyR) {
///       print('Changing color to red.');
///       setState(() {
///         _color = Colors.red;
///       });
///       return true;
///     } else if (event.logicalKey == LogicalKeyboardKey.keyG) {
///       print('Changing color to green.');
///       setState(() {
///         _color = Colors.green;
///       });
///       return true;
///     } else if (event.logicalKey == LogicalKeyboardKey.keyB) {
///       print('Changing color to blue.');
///       setState(() {
///         _color = Colors.blue;
///       });
///       return true;
///     }
///   }
///   return false;
/// }
///
/// @override
/// Widget build(BuildContext context) {
///   final TextTheme textTheme = Theme.of(context).textTheme;
///   return FocusScope(
///     debugLabel: 'Scope',
///     autofocus: true,
///     child: DefaultTextStyle(
///       style: textTheme.headline4,
///       child: Focus(
///         onKey: _handleKeyPress,
///         debugLabel: 'Button',
///         child: Builder(
///           builder: (BuildContext context) {
///             final FocusNode focusNode = Focus.of(context);
///             final bool hasFocus = focusNode.hasFocus;
///             return GestureDetector(
///               onTap: () {
///                 if (hasFocus) {
///                   focusNode.unfocus();
///                 } else {
///                   focusNode.requestFocus();
///                 }
///               },
///               child: Center(
///                 child: Container(
///                   width: 400,
///                   height: 100,
///                   alignment: Alignment.center,
///                   color: hasFocus ? _color : Colors.white,
///                   child: Text(hasFocus ? "I'm in color! Press R,G,B!" : 'Press to focus'),
///                 ),
///               ),
///             );
///           },
///         ),
///       ),
///     ),
///   );
/// }
/// ```
/// {@end-tool}
///
/// {@tool dartpad --template=stateless_widget_material}
/// This example shows how to wrap another widget in a [Focus] widget to make it
/// focusable. It wraps a [Container], and changes the container's color when it
/// is set as the [FocusManager.primaryFocus].
///
/// If you also want to handle mouse hover and/or keyboard actions on a widget,
/// consider using a [FocusableActionDetector], which combines several different
/// widgets to provide those capabilities.
///
/// ```dart preamble
/// class FocusableText extends StatelessWidget {
///   const FocusableText(this.data, {Key key, this.autofocus}) : super(key: key);
///
///   /// The string to display as the text for this widget.
///   final String data;
///
///   /// Whether or not to focus this widget initially if nothing else is focused.
///   final bool autofocus;
///
///   @override
///   Widget build(BuildContext context) {
///     return Focus(
///       autofocus: autofocus,
///       child: Builder(builder: (BuildContext context) {
///         // The contents of this Builder are being made focusable. It is inside
///         // of a Builder because the builder provides the correct context
///         // variable for Focus.of() to be able to find the Focus widget that is
///         // the Builder's parent. Without the builder, the context variable used
///         // would be the one given the FocusableText build function, and that
///         // would start looking for a Focus widget ancestor of the FocusableText
///         // instead of finding the one inside of its build function.
///         return Container(
///           padding: EdgeInsets.all(8.0),
///           // Change the color based on whether or not this Container has focus.
///           color: Focus.of(context).hasPrimaryFocus ? Colors.black12 : null,
///           child: Text(data),
///         );
///       }),
///     );
///   }
/// }
/// ```
///
/// ```dart
/// Widget build(BuildContext context) {
///   return Scaffold(
///     body: ListView.builder(
///       itemBuilder: (context, index) => FocusableText(
///         'Item $index',
///         autofocus: index == 0,
///       ),
///       itemCount: 50,
///     ),
///   );
/// }
/// ```
/// {@end-tool}
///
/// {@tool dartpad --template=stateful_widget_material}
/// This example shows how to focus a newly-created widget immediately after it
/// is created.
///
/// The focus node will not actually be given the focus until after the frame in
/// which it has requested focus is drawn, so it is OK to call
/// [FocusNode.requestFocus] on a node which is not yet in the focus tree.
///
/// ```dart
/// int focusedChild = 0;
/// List<Widget> children = <Widget>[];
/// List<FocusNode> childFocusNodes = <FocusNode>[];
///
/// @override
/// void initState() {
///   super.initState();
///   // Add the first child.
///   _addChild();
/// }
///
/// @override
/// void dispose() {
///   super.dispose();
///   childFocusNodes.forEach((FocusNode node) => node.dispose());
/// }
///
/// void _addChild() {
///   // Calling requestFocus here creates a deferred request for focus, since the
///   // node is not yet part of the focus tree.
///   childFocusNodes
///       .add(FocusNode(debugLabel: 'Child ${children.length}')..requestFocus());
///
///   children.add(Padding(
///     padding: const EdgeInsets.all(2.0),
///     child: ActionChip(
///       focusNode: childFocusNodes.last,
///       label: Text('CHILD ${children.length}'),
///       onPressed: () {},
///     ),
///   ));
/// }
///
/// @override
/// Widget build(BuildContext context) {
///   return Scaffold(
///     body: Center(
///       child: Wrap(
///         children: children,
///       ),
///     ),
///     floatingActionButton: FloatingActionButton(
///       onPressed: () {
///         setState(() {
///           focusedChild = children.length;
///           _addChild();
///         });
///       },
///       child: Icon(Icons.add),
///     ),
///   );
/// }
/// ```
/// {@end-tool}
///
/// See also:
///
///  * [FocusNode], which represents a node in the focus hierarchy and
///    [FocusNode]'s API documentation includes a detailed explanation of its role
///    in the overall focus system.
///  * [FocusScope], a widget that manages a group of focusable widgets using a
///    [FocusScopeNode].
///  * [FocusScopeNode], a node that collects focus nodes into a group for
///    traversal.
///  * [FocusManager], a singleton that manages the primary focus and
///    distributes key events to focused nodes.
///  * [FocusTraversalPolicy], an object used to determine how to move the focus
///    to other nodes.
///  * [FocusTraversalGroup], a widget that groups together and imposes a
///    traversal policy on the [Focus] nodes below it in the widget hierarchy.
class Focus extends StatefulWidget {
  /// Creates a widget that manages a [FocusNode].
  ///
  /// The [child] argument is required and must not be null.
  ///
  /// The [autofocus] argument must not be null.
  const Focus({
    Key key,
    @required this.child,
    this.focusNode,
    this.autofocus = false,
    this.onFocusChange,
    this.onKey,
    this.debugLabel,
    this.canRequestFocus,
    this.descendantsAreFocusable = true,
    this.skipTraversal,
    this.includeSemantics = true,
  })  : assert(child != null),
        assert(autofocus != null),
        assert(descendantsAreFocusable != null),
        assert(includeSemantics != null),
        super(key: key);

  /// A debug label for this widget.
  ///
  /// Not used for anything except to be printed in the diagnostic output from
  /// [toString] or [toStringDeep]. Also unused if a [focusNode] is provided,
  /// since that node can have its own [FocusNode.debugLabel].
  ///
  /// To get a string with the entire tree, call [debugDescribeFocusTree]. To
  /// print it to the console call [debugDumpFocusTree].
  ///
  /// Defaults to null.
  final String debugLabel;

  /// The child widget of this [Focus].
  ///
  /// {@macro flutter.widgets.child}
  final Widget child;

  /// Handler for keys pressed when this object or one of its children has
  /// focus.
  ///
  /// Key events are first given to the [FocusNode] that has primary focus, and
  /// if its [onKey] method return false, then they are given to each ancestor
  /// node up the focus hierarchy in turn. If an event reaches the root of the
  /// hierarchy, it is discarded.
  ///
  /// This is not the way to get text input in the manner of a text field: it
  /// leaves out support for input method editors, and doesn't support soft
  /// keyboards in general. For text input, consider [TextField],
  /// [EditableText], or [CupertinoTextField] instead, which do support these
  /// things.
  final FocusOnKeyCallback onKey;

  /// Handler called when the focus changes.
  ///
  /// Called with true if this widget's node gains focus, and false if it loses
  /// focus.
  final ValueChanged<bool> onFocusChange;

  /// {@template flutter.widgets.Focus.autofocus}
  /// True if this widget will be selected as the initial focus when no other
  /// node in its scope is currently focused.
  ///
  /// Ideally, there is only one widget with autofocus set in each [FocusScope].
  /// If there is more than one widget with autofocus set, then the first one
  /// added to the tree will get focus.
  ///
  /// Must not be null. Defaults to false.
  /// {@endtemplate}
  final bool autofocus;

  /// {@template flutter.widgets.Focus.focusNode}
  /// An optional focus node to use as the focus node for this widget.
  ///
  /// If one is not supplied, then one will be automatically allocated, owned,
  /// and managed by this widget. The widget will be focusable even if a
  /// [focusNode] is not supplied. If supplied, the given `focusNode` will be
  /// _hosted_ by this widget, but not owned. See [FocusNode] for more
  /// information on what being hosted and/or owned implies.
  ///
  /// Supplying a focus node is sometimes useful if an ancestor to this widget
  /// wants to control when this widget has the focus. The owner will be
  /// responsible for calling [FocusNode.dispose] on the focus node when it is
  /// done with it, but this widget will attach/detach and reparent the node
  /// when needed.
  /// {@endtemplate}
  final FocusNode focusNode;

  /// Sets the [FocusNode.skipTraversal] flag on the focus node so that it won't
  /// be visited by the [FocusTraversalPolicy].
  ///
  /// This is sometimes useful if a [Focus] widget should receive key events as
  /// part of the focus chain, but shouldn't be accessible via focus traversal.
  ///
  /// This is different from [FocusNode.canRequestFocus] because it only implies
  /// that the widget can't be reached via traversal, not that it can't be
  /// focused. It may still be focused explicitly.
  final bool skipTraversal;

  /// {@template flutter.widgets.Focus.includeSemantics}
  /// Include semantics information in this widget.
  ///
  /// If true, this widget will include a [Semantics] node that indicates the
  /// [SemanticsProperties.focusable] and [SemanticsProperties.focused]
  /// properties.
  ///
  /// It is not typical to set this to false, as that can affect the semantics
  /// information available to accessibility systems.
  ///
  /// Must not be null, defaults to true.
  /// {@endtemplate}
  final bool includeSemantics;

  /// {@template flutter.widgets.Focus.canRequestFocus}
  /// If true, this widget may request the primary focus.
  ///
  /// Defaults to true.  Set to false if you want the [FocusNode] this widget
  /// manages to do nothing when [FocusNode.requestFocus] is called on it. Does
  /// not affect the children of this node, and [FocusNode.hasFocus] can still
  /// return true if this node is the ancestor of the primary focus.
  ///
  /// This is different than [Focus.skipTraversal] because [Focus.skipTraversal]
  /// still allows the widget to be focused, just not traversed to.
  ///
  /// Setting [FocusNode.canRequestFocus] to false implies that the widget will
  /// also be skipped for traversal purposes.
  ///
  /// See also:
  ///
  /// * [FocusTraversalGroup], a widget that sets the traversal policy for its
  ///   descendants.
  /// * [FocusTraversalPolicy], a class that can be extended to describe a
  ///   traversal policy.
  /// {@endtemplate}
  final bool canRequestFocus;

  /// {@template flutter.widgets.Focus.descendantsAreFocusable}
  /// If false, will make this widget's descendants unfocusable.
  ///
  /// Defaults to true. Does not affect focusability of this node (just its
  /// descendants): for that, use [FocusNode.canRequestFocus].
  ///
  /// If any descendants are focused when this is set to false, they will be
  /// unfocused. When `descendantsAreFocusable` is set to true again, they will
  /// not be refocused, although they will be able to accept focus again.
  ///
  /// Does not affect the value of [FocusNode.canRequestFocus] on the
  /// descendants.
  ///
  /// See also:
  ///
  /// * [ExcludeFocus], a widget that uses this property to conditionally
  ///   exclude focus for a subtree.
  /// * [FocusTraversalGroup], a widget used to group together and configure the
  ///   focus traversal policy for a widget subtree that has a
  ///   `descendantsAreFocusable` parameter to conditionally block focus for a
  ///   subtree.
  /// {@endtemplate}
  final bool descendantsAreFocusable;

  /// Returns the [focusNode] of the [Focus] that most tightly encloses the
  /// given [BuildContext].
  ///
  /// If no [Focus] node is found before reaching the nearest [FocusScope]
  /// widget, or there is no [Focus] widget in scope, then this method will
  /// throw an exception. To return null instead of throwing, pass true for
  /// [nullOk].
  ///
  /// The [context] and [nullOk] arguments must not be null.
  ///
  /// Calling this function creates a dependency that will rebuild the given
  /// context when the focus changes.
  static FocusNode of(BuildContext context, { bool nullOk = false, bool scopeOk = false }) {
    assert(context != null);
    assert(nullOk != null);
    assert(scopeOk != null);
    final _FocusMarker marker = context.dependOnInheritedWidgetOfExactType<_FocusMarker>();
    final FocusNode node = marker?.notifier;
    if (node == null) {
      if (!nullOk) {
        throw FlutterError(
          'Focus.of() was called with a context that does not contain a Focus widget.\n'
          'No Focus widget ancestor could be found starting from the context that was passed to '
          'Focus.of(). This can happen because you are using a widget that looks for a Focus '
          'ancestor, and do not have a Focus widget descendant in the nearest FocusScope.\n'
          'The context used was:\n'
          '  $context'
        );
      }
      return null;
    }
    if (!scopeOk && node is FocusScopeNode) {
      if (!nullOk) {
        throw FlutterError(
          'Focus.of() was called with a context that does not contain a Focus between the given '
          'context and the nearest FocusScope widget.\n'
          'No Focus ancestor could be found starting from the context that was passed to '
          'Focus.of() to the point where it found the nearest FocusScope widget. This can happen '
          'because you are using a widget that looks for a Focus ancestor, and do not have a '
          'Focus widget ancestor in the current FocusScope.\n'
          'The context used was:\n'
          '  $context'
        );
      }
      return null;
    }
    return node;
  }

  /// Returns true if the nearest enclosing [Focus] widget's node is focused.
  ///
  /// A convenience method to allow build methods to write:
  /// `Focus.isAt(context)` to get whether or not the nearest [Focus] above them
  /// in the widget hierarchy currently has the input focus.
  ///
  /// Returns false if no [Focus] widget is found before reaching the nearest
  /// [FocusScope], or if the root of the focus tree is reached without finding
  /// a [Focus] widget.
  ///
  /// Calling this function creates a dependency that will rebuild the given
  /// context when the focus changes.
  static bool isAt(BuildContext context) => Focus.of(context, nullOk: true)?.hasFocus ?? false;

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('debugLabel', debugLabel, defaultValue: null));
    properties.add(FlagProperty('autofocus', value: autofocus, ifTrue: 'AUTOFOCUS', defaultValue: false));
    properties.add(FlagProperty('canRequestFocus', value: canRequestFocus, ifFalse: 'NOT FOCUSABLE', defaultValue: false));
    properties.add(FlagProperty('descendantsAreFocusable', value: descendantsAreFocusable, ifFalse: 'DESCENDANTS UNFOCUSABLE', defaultValue: true));
    properties.add(DiagnosticsProperty<FocusNode>('focusNode', focusNode, defaultValue: null));
  }

  @override
  _FocusState createState() => _FocusState();
}

class _FocusState extends State<Focus> {
  FocusNode _internalNode;
  FocusNode get focusNode => widget.focusNode ?? _internalNode;
  bool _hasPrimaryFocus;
  bool _canRequestFocus;
  bool _descendantsAreFocusable;
  bool _didAutofocus = false;
  FocusAttachment _focusAttachment;

  @override
  void initState() {
    super.initState();
    _initNode();
  }

  void _initNode() {
    if (widget.focusNode == null) {
      // Only create a new node if the widget doesn't have one.
      // This calls a function instead of just allocating in place because
      // _createNode is overridden in _FocusScopeState.
      _internalNode ??= _createNode();
    }
    if (widget.descendantsAreFocusable != null) {
      focusNode.descendantsAreFocusable = widget.descendantsAreFocusable;
    }
    if (widget.skipTraversal != null) {
      focusNode.skipTraversal = widget.skipTraversal;
    }
    if (widget.canRequestFocus != null) {
      focusNode.canRequestFocus = widget.canRequestFocus;
    }
    _canRequestFocus = focusNode.canRequestFocus;
    _descendantsAreFocusable = focusNode.descendantsAreFocusable;
    _hasPrimaryFocus = focusNode.hasPrimaryFocus;
    _focusAttachment = focusNode.attach(context, onKey: widget.onKey);

    // Add listener even if the _internalNode existed before, since it should
    // not be listening now if we're re-using a previous one because it should
    // have already removed its listener.
    focusNode.addListener(_handleFocusChanged);
  }

  FocusNode _createNode() {
    return FocusNode(
      debugLabel: widget.debugLabel,
      canRequestFocus: widget.canRequestFocus ?? true,
      descendantsAreFocusable: widget.descendantsAreFocusable ?? false,
      skipTraversal: widget.skipTraversal ?? false,
    );
  }

  @override
  void dispose() {
    // Regardless of the node owner, we need to remove it from the tree and stop
    // listening to it.
    focusNode.removeListener(_handleFocusChanged);
    _focusAttachment.detach();

    // Don't manage the lifetime of external nodes given to the widget, just the
    // internal node.
    _internalNode?.dispose();
    super.dispose();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _focusAttachment?.reparent();
    _handleAutofocus();
  }

  void _handleAutofocus() {
    if (!_didAutofocus && widget.autofocus) {
      FocusScope.of(context).autofocus(focusNode);
      _didAutofocus = true;
    }
  }

  @override
  void deactivate() {
    super.deactivate();
    // The focus node's location in the tree is no longer valid here. But
    // we can't unfocus or remove the node from the tree because if the widget
    // is moved to a different part of the tree (via global key) it should
    // retain its focus state. That's why we temporarily park it on the root
    // focus node (via reparent) until it either gets moved to a different part
    // of the tree (via didChangeDependencies) or until it is disposed.
    _focusAttachment?.reparent();
    _didAutofocus = false;
  }

  @override
  void didUpdateWidget(Focus oldWidget) {
    super.didUpdateWidget(oldWidget);
    assert(() {
      // Only update the debug label in debug builds, and only if we own the
      // node.
      if (oldWidget.debugLabel != widget.debugLabel && _internalNode != null) {
        _internalNode.debugLabel = widget.debugLabel;
      }
      return true;
    }());

    if (oldWidget.focusNode == widget.focusNode) {
      if (widget.skipTraversal != null) {
        focusNode.skipTraversal = widget.skipTraversal;
      }
      if (widget.canRequestFocus != null) {
        focusNode.canRequestFocus = widget.canRequestFocus;
      }
      if (widget.descendantsAreFocusable != null) {
        focusNode.descendantsAreFocusable = widget.descendantsAreFocusable;
      }
    } else {
      _focusAttachment.detach();
      focusNode.removeListener(_handleFocusChanged);
      _initNode();
    }

    if (oldWidget.autofocus != widget.autofocus) {
      _handleAutofocus();
    }
  }

  void _handleFocusChanged() {
    final bool hasPrimaryFocus = focusNode.hasPrimaryFocus;
    final bool canRequestFocus = focusNode.canRequestFocus;
    final bool descendantsAreFocusable = focusNode.descendantsAreFocusable;
    if (widget.onFocusChange != null) {
      widget.onFocusChange(focusNode.hasFocus);
    }
    if (_hasPrimaryFocus != hasPrimaryFocus) {
      setState(() {
        _hasPrimaryFocus = hasPrimaryFocus;
      });
    }
    if (_canRequestFocus != canRequestFocus) {
      setState(() {
        _canRequestFocus = canRequestFocus;
      });
    }
    if (_descendantsAreFocusable != descendantsAreFocusable) {
      setState(() {
        _descendantsAreFocusable = descendantsAreFocusable;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    _focusAttachment.reparent();
    Widget child = widget.child;
    if (widget.includeSemantics) {
      child = Semantics(
        focusable: _canRequestFocus,
        focused: _hasPrimaryFocus,
        child: widget.child,
      );
    }
    return _FocusMarker(
      node: focusNode,
      child: child,
    );
  }
}

/// A [FocusScope] is similar to a [Focus], but also serves as a scope for its
/// descendants, restricting focus traversal to the scoped controls.
///
/// For example a new [FocusScope] is created automatically when a route is
/// pushed, keeping the focus traversal from moving to a control in a previous
/// route.
///
/// If you just want to group widgets together in a group so that they are
/// traversed in a particular order, but the focus can still leave the group,
/// use a [FocusTraversalGroup].
///
/// Like [Focus], [FocusScope] provides an [onFocusChange] as a way to be
/// notified when the focus is given to or removed from this widget.
///
/// The [onKey] argument allows specification of a key event handler that is
/// invoked when this node or one of its children has focus. Keys are handed to
/// the primary focused widget first, and then they propagate through the
/// ancestors of that node, stopping if one of them returns true from [onKey],
/// indicating that it has handled the event.
///
/// Managing a [FocusScopeNode] means managing its lifecycle, listening for
/// changes in focus, and re-parenting it when needed to keep the focus
/// hierarchy in sync with the widget hierarchy. This widget does all of those
/// things for you. See [FocusScopeNode] for more information about the details
/// of what node management entails if you are not using a [FocusScope] widget
/// and you need to do it yourself.
///
/// [FocusScopeNode]s remember the last [FocusNode] that was focused within
/// their descendants, and can move that focus to the next/previous node, or a
/// node in a particular direction when the [FocusNode.nextFocus],
/// [FocusNode.previousFocus], or [FocusNode.focusInDirection] are called on a
/// [FocusNode] or [FocusScopeNode].
///
/// To move the focus, use methods on [FocusNode] by getting the [FocusNode]
/// through the [of] method. For instance, to move the focus to the next node in
/// the focus traversal order, call `Focus.of(context).nextFocus()`. To unfocus
/// a widget, call `Focus.of(context).unfocus()`.
///
/// {@tool dartpad --template=stateful_widget_material}
/// This example demonstrates using a [FocusScope] to restrict focus to a particular
/// portion of the app. In this case, restricting focus to the visible part of a
/// Stack.
///
/// ```dart preamble
/// /// A demonstration pane.
/// ///
/// /// This is just a separate widget to simplify the example.
/// class Pane extends StatelessWidget {
///   const Pane({
///     Key key,
///     this.focusNode,
///     this.onPressed,
///     this.child,
///     this.backgroundColor,
///     this.icon,
///   }) : super(key: key);
///
///   final FocusNode focusNode;
///   final VoidCallback onPressed;
///   final Widget child;
///   final Color backgroundColor;
///   final Widget icon;
///
///   @override
///   Widget build(BuildContext context) {
///     return Material(
///       color: backgroundColor,
///       child: Stack(
///         fit: StackFit.expand,
///         children: <Widget>[
///           Center(
///             child: child,
///           ),
///           Align(
///             alignment: Alignment.topLeft,
///             child: IconButton(
///               autofocus: true,
///               focusNode: focusNode,
///               onPressed: onPressed,
///               icon: icon,
///             ),
///           ),
///         ],
///       ),
///     );
///   }
/// }
/// ```
///
/// ```dart
///   bool backdropIsVisible = false;
///   FocusNode backdropNode = FocusNode(debugLabel: 'Close Backdrop Button');
///   FocusNode foregroundNode = FocusNode(debugLabel: 'Option Button');
///
///   @override
///   void dispose() {
///     super.dispose();
///     backdropNode.dispose();
///     foregroundNode.dispose();
///   }
///
///   Widget _buildStack(BuildContext context, BoxConstraints constraints) {
///     Size stackSize = constraints.biggest;
///     return Stack(
///       fit: StackFit.expand,
///       // The backdrop is behind the front widget in the Stack, but the widgets
///       // would still be active and traversable without the FocusScope.
///       children: <Widget>[
///         // TRY THIS: Try removing this FocusScope entirely to see how it affects
///         // the behavior. Without this FocusScope, the "ANOTHER BUTTON TO FOCUS"
///         // button, and the IconButton in the backdrop Pane would be focusable
///         // even when the backdrop wasn't visible.
///         FocusScope(
///           // TRY THIS: Try commenting out this line. Notice that the focus
///           // starts on the backdrop and is stuck there? It seems like the app is
///           // non-responsive, but it actually isn't. This line makes sure that
///           // this focus scope and its children can't be focused when they're not
///           // visible. It might help to make the background color of the
///           // foreground pane semi-transparent to see it clearly.
///           canRequestFocus: backdropIsVisible,
///           child: Pane(
///             icon: Icon(Icons.close),
///             focusNode: backdropNode,
///             backgroundColor: Colors.lightBlue,
///             onPressed: () => setState(() => backdropIsVisible = false),
///             child: Column(
///               mainAxisAlignment: MainAxisAlignment.center,
///               children: <Widget>[
///                 // This button would be not visible, but still focusable from
///                 // the foreground pane without the FocusScope.
///                 ElevatedButton(
///                   onPressed: () => print('You pressed the other button!'),
///                   child: Text('ANOTHER BUTTON TO FOCUS'),
///                 ),
///                 DefaultTextStyle(
///                     style: Theme.of(context).textTheme.headline2,
///                     child: Text('BACKDROP')),
///               ],
///             ),
///           ),
///         ),
///         AnimatedPositioned(
///           curve: Curves.easeInOut,
///           duration: const Duration(milliseconds: 300),
///           top: backdropIsVisible ? stackSize.height * 0.9 : 0.0,
///           width: stackSize.width,
///           height: stackSize.height,
///           onEnd: () {
///             if (backdropIsVisible) {
///               backdropNode.requestFocus();
///             } else {
///               foregroundNode.requestFocus();
///             }
///           },
///           child: Pane(
///             icon: Icon(Icons.menu),
///             focusNode: foregroundNode,
///             // TRY THIS: Try changing this to Colors.green.withOpacity(0.8) to see for
///             // yourself that the hidden components do/don't get focus.
///             backgroundColor: Colors.green,
///             onPressed: backdropIsVisible
///                 ? null
///                 : () => setState(() => backdropIsVisible = true),
///             child: DefaultTextStyle(
///                 style: Theme.of(context).textTheme.headline2,
///                 child: Text('FOREGROUND')),
///           ),
///         ),
///       ],
///     );
///   }
///
///   @override
///   Widget build(BuildContext context) {
///     // Use a LayoutBuilder so that we can base the size of the stack on the size
///     // of its parent.
///     return LayoutBuilder(builder: _buildStack);
///   }
/// ```
/// {@end-tool}
///
/// See also:
///
///  * [FocusScopeNode], which represents a scope node in the focus hierarchy.
///  * [FocusNode], which represents a node in the focus hierarchy and has an
///    explanation of the focus system.
///  * [Focus], a widget that manages a [FocusNode] and allows easy access to
///    managing focus without having to manage the node.
///  * [FocusManager], a singleton that manages the focus and distributes key
///    events to focused nodes.
///  * [FocusTraversalPolicy], an object used to determine how to move the focus
///    to other nodes.
///  * [FocusTraversalGroup], a widget used to configure the focus traversal
///    policy for a widget subtree.
class FocusScope extends Focus {
  /// Creates a widget that manages a [FocusScopeNode].
  ///
  /// The [child] argument is required and must not be null.
  ///
  /// The [autofocus] argument must not be null.
  const FocusScope({
    Key key,
    FocusScopeNode node,
    @required Widget child,
    bool autofocus = false,
    ValueChanged<bool> onFocusChange,
    bool canRequestFocus,
    bool skipTraversal,
    FocusOnKeyCallback onKey,
    String debugLabel,
  })  : assert(child != null),
        assert(autofocus != null),
        super(
          key: key,
          child: child,
          focusNode: node,
          autofocus: autofocus,
          onFocusChange: onFocusChange,
          canRequestFocus: canRequestFocus,
          skipTraversal: skipTraversal,
          onKey: onKey,
          debugLabel: debugLabel,
        );

  /// Returns the [FocusScopeNode] of the [FocusScope] that most tightly
  /// encloses the given [context].
  ///
  /// If this node doesn't have a [Focus] widget ancestor, then the
  /// [FocusManager.rootScope] is returned.
  ///
  /// The [context] argument must not be null.
  static FocusScopeNode of(BuildContext context) {
    assert(context != null);
    final _FocusMarker marker = context.dependOnInheritedWidgetOfExactType<_FocusMarker>();
    return marker?.notifier?.nearestScope ?? context.owner.focusManager.rootScope;
  }

  @override
  _FocusScopeState createState() => _FocusScopeState();
}

class _FocusScopeState extends _FocusState {
  @override
  FocusScopeNode _createNode() {
    return FocusScopeNode(
      debugLabel: widget.debugLabel,
      canRequestFocus: widget.canRequestFocus ?? true,
      skipTraversal: widget.skipTraversal ?? false,
    );
  }

  @override
  Widget build(BuildContext context) {
    _focusAttachment.reparent();
    return Semantics(
      explicitChildNodes: true,
      child: _FocusMarker(
        node: focusNode,
        child: widget.child,
      ),
    );
  }
}

// The InheritedWidget marker for Focus and FocusScope.
class _FocusMarker extends InheritedNotifier<FocusNode> {
  const _FocusMarker({
    Key key,
    @required FocusNode node,
    @required Widget child,
  })  : assert(node != null),
        assert(child != null),
        super(key: key, notifier: node, child: child);
}

/// A widget that controls whether or not the descendants of this widget are
/// focusable.
///
/// Does not affect the value of [Focus.canRequestFocus] on the descendants.
///
/// See also:
///
///  * [Focus], a widget for adding and managing a [FocusNode] in the widget tree.
///  * [FocusTraversalGroup], a widget that groups widgets for focus traversal,
///    and can also be used in the same way as this widget by setting its
///    `descendantsAreFocusable` attribute.
class ExcludeFocus extends StatelessWidget {
  /// Const constructor for [ExcludeFocus] widget.
  ///
  /// The [excluding] argument must not be null.
  ///
  /// The [child] argument is required, and must not be null.
  const ExcludeFocus({
    Key key,
    this.excluding = true,
    @required this.child,
  })  : assert(excluding != null),
        assert(child != null),
        super(key: key);

  /// If true, will make this widget's descendants unfocusable.
  ///
  /// Defaults to true.
  ///
  /// If any descendants are focused when this is set to true, they will be
  /// unfocused. When `excluding` is set to false again, they will not be
  /// refocused, although they will be able to accept focus again.
  ///
  /// Does not affect the value of [FocusNode.canRequestFocus] on the
  /// descendants.
  ///
  /// See also:
  ///
  /// * [Focus.descendantsAreFocusable], the attribute of a [Focus] widget that
  ///   controls this same property for focus widgets.
  /// * [FocusTraversalGroup], a widget used to group together and configure the
  ///   focus traversal policy for a widget subtree that has a
  ///   `descendantsAreFocusable` parameter to conditionally block focus for a
  ///   subtree.
  final bool excluding;

  /// The child widget of this [ExcludeFocus].
  ///
  /// {@macro flutter.widgets.child}
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return Focus(
      canRequestFocus: false,
      skipTraversal: true,
      includeSemantics: false,
      descendantsAreFocusable: !excluding,
      child: child,
    );
  }
}
