// 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';
import 'package:flutter/rendering.dart';

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

class SampleApp extends StatefulWidget {
  const SampleApp({super.key});

  @override
  State<SampleApp> createState() => _SampleAppState();
}

class _SampleAppState extends State<SampleApp> {
  // This can be toggled using buttons in the UI to change which layout render object is used.
  bool _compact = false;

  // This is the content we show in the rendering.
  //
  // Headline and Paragraph are simple custom widgets defined below.
  //
  // Any widget _could_ be specified here, and would render fine.
  // The Headline and Paragraph widgets are used so that the renderer
  // can distinguish between the kinds of content and use different
  // spacing between different children.
  static const List<Widget> body = <Widget>[
    Headline('Bugs that improve T for future bugs'),
    Paragraph(
      'The best bugs to fix are those that make us more productive '
      'in the future. Reducing test flakiness, reducing technical '
      'debt, increasing the number of team members who are able to '
      'review code confidently and well: this all makes future bugs '
      'easier to fix, which is a huge multiplier to our overall '
      'effectiveness and thus to developer happiness.',
    ),
    Headline('Bugs affecting more people are more valuable (maximize N)'),
    Paragraph(
      'We will make more people happier if we fix a bug experienced by more people.'
    ),
    Paragraph(
      'One thing to be careful about is to think about the number of '
      'people we are ignoring in our metrics. For example, if we had '
      'a bug that prevented our product from working on Windows, we '
      'would have no Windows users, so the bug would affect nobody. '
      'However, fixing the bug would enable millions of developers '
      "to use our product, and that's the number that counts."
    ),
    Headline('Bugs with greater impact on developers are more valuable (maximize ΔH)'),
    Paragraph(
      'A slight improvement to the user experience is less valuable '
      'than a greater improvement. For example, if our application, '
      'under certain conditions, shows a message with a typo, and '
      'then crashes because of an off-by-one error in the code, '
      'fixing the crash is a higher priority than fixing the typo.'
    ),
  ];

  // This is the description of the demo's interface.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Custom Render Boxes'),
          // There are two buttons over to the top right of the demo that let you
          // toggle between the two rendering modes.
          actions: <Widget>[
            IconButton(
              icon: const Icon(Icons.density_small),
              isSelected: _compact,
              onPressed: () {
                setState(() { _compact = true; });
              },
            ),
            IconButton(
              icon: const Icon(Icons.density_large),
              isSelected: !_compact,
              onPressed: () {
                setState(() { _compact = false; });
              },
            ),
          ],
        ),
        body: SingleChildScrollView(
          padding: const EdgeInsets.symmetric(horizontal: 30.0, vertical: 20.0),
          // CompactLayout and OpenLayout are the two rendering widgets defined below.
          child: _compact ? const CompactLayout(children: body) : const OpenLayout(children: body),
        ),
      ),
    );
  }
}

// Headline and Paragraph are just wrappers around the Text widget, but they
// also introduce a TextCategory widget that the CompactLayout and OpenLayout
// widgets can read to determine what kind of child is being rendered.

class Headline extends StatelessWidget {
  const Headline(this.text, { super.key });

  final String text;

  @override
  Widget build(BuildContext context) {
    return TextCategory(
      category: 'headline',
      child: Text(text, style: Theme.of(context).textTheme.titleLarge),
    );
  }
}

class Paragraph extends StatelessWidget {
  const Paragraph(this.text, { super.key });

  final String text;

  @override
  Widget build(BuildContext context) {
    return TextCategory(
      category: 'paragraph',
      child: Text(text, style: Theme.of(context).textTheme.bodyLarge),
    );
  }
}

// This is the ParentDataWidget that allows us to specify what kind of child
// is being rendered. It allows information to be shared with the render object
// without violating the principle of agnostic composition (wherein parents should
// work with any child, not only support a fixed set of children).
class TextCategory extends ParentDataWidget<TextFlowParentData> {
  const TextCategory({ super.key, required this.category, required super.child });

  final String category;

  @override
  void applyParentData(RenderObject renderObject) {
    final TextFlowParentData parentData = renderObject.parentData! as TextFlowParentData;
    if (parentData.category != category) {
      parentData.category = category;
      renderObject.parent!.markNeedsLayout();
    }
  }

  @override
  Type get debugTypicalAncestorWidgetClass => OpenLayout;
}

// This is one of the two layout variants. It is a widget that defers to
// a render object defined below (RenderCompactLayout).
class CompactLayout extends MultiChildRenderObjectWidget {
  const CompactLayout({ super.key, super.children });

  @override
  RenderCompactLayout createRenderObject(BuildContext context) {
    return RenderCompactLayout();
  }

  @override
  void updateRenderObject(BuildContext context, RenderCompactLayout renderObject) {
    // nothing to update
  }
}

// This is the other of the two layout variants. It is a widget that defers to a
// render object defined below (RenderOpenLayout).
class OpenLayout extends MultiChildRenderObjectWidget {
  const OpenLayout({ super.key, super.children });

  @override
  RenderOpenLayout createRenderObject(BuildContext context) {
    return RenderOpenLayout();
  }

  @override
  void updateRenderObject(BuildContext context, RenderOpenLayout renderObject) {
    // nothing to update
  }
}

// This is the data structure that contains the kind of data that can be
// passed to the parent to label the child. It is literally stored on
// the RenderObject child, in its "parentData" field.
class TextFlowParentData extends ContainerBoxParentData<RenderBox> {
  String category = '';
}

// This is the bulk of the layout logic. (It's similar to RenderListBody,
// but only supports vertical layout.) It has no properties.
//
// This is an abstract class that is then extended by RenderCompactLayout and
// RenderOpenLayout to get different layouts based on the children's categories,
// as stored in the ParentData structure defined above.
//
// The documentation for the RenderBox class and its members provides much
// more detail on how to implement each of the methods below.
abstract class RenderTextFlow extends RenderBox
    with ContainerRenderObjectMixin<RenderBox, TextFlowParentData>,
         RenderBoxContainerDefaultsMixin<RenderBox, TextFlowParentData> {
  RenderTextFlow({ List<RenderBox>? children }) {
    addAll(children);
  }

  @override
  void setupParentData(RenderBox child) {
    if (child.parentData is! TextFlowParentData) {
      child.parentData = TextFlowParentData();
    }
  }

  // This is the function that is overridden by the subclasses to do the
  // actual decision about the space to use between children.
  double spacingBetween(String before, String after);

  // The next few functions are the layout functions. In each case we walk the
  // children, calling each one to determine the geometry of the child, and use
  // that to determine the layout.

  // The first two functions compute the intrinsic width of the render object,
  // as seen when using the IntrinsicWidth widget.
  //
  // They essentially defer to the widest child.

  @override
  double computeMinIntrinsicWidth(double height) {
    double width = 0.0;
    RenderBox? child = firstChild;
    while (child != null) {
      final double childWidth = child.getMinIntrinsicWidth(height);
      if (childWidth > width) {
        width = childWidth;
      }
      child = childAfter(child);
    }
    return width;
  }

  @override
  double computeMaxIntrinsicWidth(double height) {
    double width = 0.0;
    RenderBox? child = firstChild;
    while (child != null) {
      final double childWidth = child.getMaxIntrinsicWidth(height);
      if (childWidth > width) {
        width = childWidth;
      }
      child = childAfter(child);
    }
    return width;
  }

  // The next two functions compute the intrinsic height of the render object,
  // as seen when using the IntrinsicHeight widget.
  //
  // They add up the height contributed by each child.
  //
  // They have to take into account the categories of the children and the
  // spacing that will be added, hence the slightly more elaborate logic.

  @override
  double computeMinIntrinsicHeight(double width) {
    String? previousCategory;
    double height = 0.0;
    RenderBox? child = firstChild;
    while (child != null) {
      final String category = (child.parentData! as TextFlowParentData).category;
      if (previousCategory != null) {
        height += spacingBetween(previousCategory, category);
      }
      height += child.getMinIntrinsicHeight(width);
      previousCategory = category;
      child = childAfter(child);
    }
    return height;
  }

  @override
  double computeMaxIntrinsicHeight(double width) {
    String? previousCategory;
    double height = 0.0;
    RenderBox? child = firstChild;
    while (child != null) {
      final String category = (child.parentData! as TextFlowParentData).category;
      if (previousCategory != null) {
        height += spacingBetween(previousCategory, category);
      }
      height += child.getMaxIntrinsicHeight(width);
      previousCategory = category;
      child = childAfter(child);
    }
    return height;
  }

  // This function implements the baseline logic. Because this class does
  // nothing special, we just defer to the default implementation in the
  // RenderBoxContainerDefaultsMixin utility class.

  @override
  double? computeDistanceToActualBaseline(TextBaseline baseline) {
    return defaultComputeDistanceToFirstActualBaseline(baseline);
  }

  // Next we have a function similar to the intrinsic methods, but for both axes
  // at the same time.

  @override
  Size computeDryLayout(BoxConstraints constraints) {
    final BoxConstraints innerConstraints = BoxConstraints.tightFor(width: constraints.maxWidth);
    String? previousCategory;
    double y = 0.0;
    RenderBox? child = firstChild;
    while (child != null) {
      final String category = (child.parentData! as TextFlowParentData).category;
      if (previousCategory != null) {
        y += spacingBetween(previousCategory, category);
      }
      final Size childSize = child.getDryLayout(innerConstraints);
      y += childSize.height;
      previousCategory = category;
      child = childAfter(child);
    }
    return constraints.constrain(Size(constraints.maxWidth, y));
  }

  // This is the core of the layout logic. Most of the time, this is the only
  // function that will be called. It computes the size and position of each
  // child, and stores it (in the parent data, as it happens!) for use during
  // the paint phase.

  @override
  void performLayout() {
    final BoxConstraints innerConstraints = BoxConstraints.tightFor(width: constraints.maxWidth);
    String? previousCategory;
    double y = 0.0;
    RenderBox? child = firstChild;
    while (child != null) {
      final String category = (child.parentData! as TextFlowParentData).category;
      if (previousCategory != null) {
        // This is where we call the function that computes the spacing between
        // the different children. The arguments are the categories, obtained
        // from the parentData property of each child.
        y += spacingBetween(previousCategory, category);
      }
      child.layout(innerConstraints, parentUsesSize: true);
      (child.parentData! as TextFlowParentData).offset = Offset(0.0, y);
      y += child.size.height;
      previousCategory = category;
      child = childAfter(child);
    }
    size = constraints.constrain(Size(constraints.maxWidth, y));
  }

  // Hit testing is normal for this widget, so we defer to the default implementation.
  @override
  bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
    return defaultHitTestChildren(result, position: position);
  }

  // Painting is normal for this widget, so we defer to the default
  // implementation. The default implementation expects to find the positions
  // configured in the parentData property of each child, which is why we
  // configure it that way in performLayout above.
  @override
  void paint(PaintingContext context, Offset offset) {
    defaultPaint(context, offset);
  }
}

// Finally we have the two render objects that implement the two layouts in this demo.

class RenderOpenLayout extends RenderTextFlow {
  @override
  double spacingBetween(String before, String after) {
    if (after == 'headline') {
      return 20.0;
    }
    if (before == 'headline') {
      return 5.0;
    }
    return 10.0;
  }
}

class RenderCompactLayout extends RenderTextFlow {
  @override
  double spacingBetween(String before, String after) {
    if (after == 'headline') {
      return 4.0;
    }
    return 2.0;
  }
}
