// 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/material.dart';

/// Flutter code sample for [ListenableBuilder].

void main() => runApp(const ListenableBuilderExample());

/// This widget listens for changes in the focus state of the subtree defined by
/// its [child] widget, changing the border and color of the container it is in
/// when it has focus.
///
/// A [FocusListenerContainer] swaps out the [BorderSide] of a border around the
/// child widget with [focusedSide], and the background color with
/// [focusedColor], when a widget that is a descendant of this widget has focus.
class FocusListenerContainer extends StatefulWidget {
  const FocusListenerContainer({
    super.key,
    this.border,
    this.padding,
    this.focusedSide,
    this.focusedColor = Colors.black12,
    required this.child,
  });

  /// This is the border that will be used when not focused, and which defines
  /// all the attributes except for the [OutlinedBorder.side] when focused.
  final OutlinedBorder? border;

  /// This is the [BorderSide] that will be used for [border] when the [child]
  /// subtree is focused.
  final BorderSide? focusedSide;

  /// This is the [Color] that will be used as the fill color for the background
  /// of the [child] when a descendant widget is focused.
  final Color? focusedColor;

  /// The padding around the inside of the container.
  final EdgeInsetsGeometry? padding;

  /// This is defines the subtree to listen to for focus changes.
  final Widget child;

  @override
  State<FocusListenerContainer> createState() => _FocusListenerContainerState();
}

class _FocusListenerContainerState extends State<FocusListenerContainer> {
  final FocusNode _focusNode = FocusNode();

  @override
  void dispose() {
    _focusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final OutlinedBorder effectiveBorder = widget.border ?? const RoundedRectangleBorder();
    return ListenableBuilder(
      listenable: _focusNode,
      child: Focus(
        focusNode: _focusNode,
        skipTraversal: true,
        canRequestFocus: false,
        child: widget.child,
      ),
      builder: (BuildContext context, Widget? child) {
        return Container(
          padding: widget.padding,
          decoration: ShapeDecoration(
            color: _focusNode.hasFocus ? widget.focusedColor : null,
            shape: effectiveBorder.copyWith(
              side: _focusNode.hasFocus ? widget.focusedSide : null,
            ),
          ),
          child: child,
        );
      },
    );
  }
}

class MyField extends StatefulWidget {
  const MyField({super.key, required this.label});

  final String label;

  @override
  State<MyField> createState() => _MyFieldState();
}

class _MyFieldState extends State<MyField> {
  final TextEditingController controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        Expanded(child: Text(widget.label)),
        Expanded(
          flex: 2,
          child: TextField(
            controller: controller,
            onEditingComplete: () {
              debugPrint('Field ${widget.label} changed to ${controller.value}');
            },
          ),
        ),
      ],
    );
  }
}

class ListenableBuilderExample extends StatelessWidget {
  const ListenableBuilderExample({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('ListenableBuilder Example')),
        body: Center(
          child: SizedBox(
            width: 300,
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  const Padding(
                    padding: EdgeInsets.only(bottom: 8),
                    child: MyField(label: 'Company'),
                  ),
                  FocusListenerContainer(
                    padding: const EdgeInsets.all(8),
                    border: const RoundedRectangleBorder(
                      side: BorderSide(
                        strokeAlign: BorderSide.strokeAlignOutside,
                      ),
                      borderRadius: BorderRadius.all(
                        Radius.circular(5),
                      ),
                    ),
                    // The border side will get wider when the subtree has focus.
                    focusedSide: const BorderSide(
                      width: 4,
                      strokeAlign: BorderSide.strokeAlignOutside,
                    ),
                    // The container background will change color to this when
                    // the subtree has focus.
                    focusedColor: Colors.blue.shade50,
                    child: const Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text('Owner:'),
                        MyField(label: 'First Name'),
                        MyField(label: 'Last Name'),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}
