build method

  1. @override
Widget build(
  1. BuildContext context
)
override

Describes the part of the user interface represented by this widget.

The framework calls this method in a number of different situations. For example:

This method can potentially be called in every frame and should not have any side effects beyond building a widget.

The framework replaces the subtree below this widget with the widget returned by this method, either by updating the existing subtree or by removing the subtree and inflating a new subtree, depending on whether the widget returned by this method can update the root of the existing subtree, as determined by calling Widget.canUpdate.

Typically implementations return a newly created constellation of widgets that are configured with information from this widget's constructor, the given BuildContext, and the internal state of this State object.

The given BuildContext contains information about the location in the tree at which this widget is being built. For example, the context provides the set of inherited widgets for this location in the tree. The BuildContext argument is always the same as the context property of this State object and will remain the same for the lifetime of this object. The BuildContext argument is provided redundantly here so that this method matches the signature for a WidgetBuilder.

Design discussion

Why is the build method on State, and not StatefulWidget?

Putting a Widget build(BuildContext context) method on State rather than putting a Widget build(BuildContext context, State state) method on StatefulWidget gives developers more flexibility when subclassing StatefulWidget.

For example, AnimatedWidget is a subclass of StatefulWidget that introduces an abstract Widget build(BuildContext context) method for its subclasses to implement. If StatefulWidget already had a build method that took a State argument, AnimatedWidget would be forced to provide its State object to subclasses even though its State object is an internal implementation detail of AnimatedWidget.

Conceptually, StatelessWidget could also be implemented as a subclass of StatefulWidget in a similar manner. If the build method were on StatefulWidget rather than State, that would not be possible anymore.

Putting the build function on State rather than StatefulWidget also helps avoid a category of bugs related to closures implicitly capturing this. If you defined a closure in a build function on a StatefulWidget, that closure would implicitly capture this, which is the current widget instance, and would have the (immutable) fields of that instance in scope:

// (this is not valid Flutter code)
class MyButton extends StatefulWidgetX {
  MyButton({super.key, required this.color});

  final Color color;

  @override
  Widget build(BuildContext context, State state) {
    return SpecialWidget(
      handler: () { print('color: $color'); },
    );
  }
}

For example, suppose the parent builds MyButton with color being blue, the $color in the print function refers to blue, as expected. Now, suppose the parent rebuilds MyButton with green. The closure created by the first build still implicitly refers to the original widget and the $color still prints blue even through the widget has been updated to green; should that closure outlive its widget, it would print outdated information.

In contrast, with the build function on the State object, closures created during build implicitly capture the State instance instead of the widget instance:

class MyButton extends StatefulWidget {
  const MyButton({super.key, this.color = Colors.teal});

  final Color color;
  // ...
}

class MyButtonState extends State<MyButton> {
  // ...
  @override
  Widget build(BuildContext context) {
    return SpecialWidget(
      handler: () { print('color: ${widget.color}'); },
    );
  }
}

Now when the parent rebuilds MyButton with green, the closure created by the first build still refers to State object, which is preserved across rebuilds, but the framework has updated that State object's widget property to refer to the new MyButton instance and ${widget.color} prints green, as expected.

See also:

  • StatefulWidget, which contains the discussion on performance considerations.

Implementation

@override
Widget build(BuildContext context) {
  widget._state = this;

  ///Set Map Size
  if (widget.getParentNode() == null &&
      (!widget.getSelected() || !widget._focusNode.hasFocus)) {
    WidgetsBinding.instance.addPostFrameCallback((c) {
      if (mounted && !widget.getSelected()) {
        RenderObject? ro = context.findRenderObject();
        if (ro != null && ro is RenderBox) {
          widget.getMindMap()?.setSize(ro.size);
        }
      }
    });
  }
  switch (widget.getMindMap()?.getMapType() ?? MapType.mind) {
    case MapType.mind:
      List<Widget> leftItems = [];
      if (widget.getNodeType() == NodeType.root ||
          widget.getNodeType() == NodeType.left) {
        for (IMindMapNode item in widget.getLeftItems()) {
          leftItems.add(item as Widget);
        }
      }
      List<Widget> rightItems = [];
      if (widget.getNodeType() == NodeType.root ||
          widget.getNodeType() == NodeType.right) {
        for (IMindMapNode item in widget.getRightItems()) {
          rightItems.add(item as Widget);
        }
      }
      return CustomPaint(
        painter: widget.getOffset() == null
            ? null
            : widget.getLink().getPainter(widget),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisSize: MainAxisSize.min,

          ///spacing: widget.getHSpace().toDouble(),
          children: [
            ///Left Items
            ...(leftItems.isEmpty ||
                    (!widget.getExpanded() &&
                        (widget.getMindMap()?.getReadOnly() ?? false))
                ? []
                : [
                    Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.end,
                      mainAxisSize: MainAxisSize.min,
                      spacing: widget.getVSpace().toDouble(),
                      children: leftItems,
                    ),
                  ]),

            ///LeftSpace
            ...(widget.getNodeType() != NodeType.right
                ? [
                    Container(
                      constraints: BoxConstraints(
                        minWidth: widget.getHSpace().toDouble(),
                        maxWidth: widget.getHSpace().toDouble(),
                        minHeight:
                            (widget.getMindMap()?.getButtonWidth() ?? 24)
                                .toDouble(),
                      ),
                      padding: EdgeInsets.fromLTRB(3, 0, 3, 0),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.end,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: [
                          ...(widget.getSelected()
                              ? (widget.getReadOnly()
                                    ? (widget.getNodeType() ==
                                                  NodeType.left &&
                                              widget.canExpand() &&
                                              widget
                                                  .getLeftItems()
                                                  .isNotEmpty &&
                                              (widget
                                                          .getMindMap()
                                                          ?.getExpandedLevel() ??
                                                      0) <=
                                                  widget.getLevel() + 1
                                          ? [
                                              ///Left Expand Button
                                              Container(
                                                constraints: BoxConstraints(
                                                  maxHeight:
                                                      (widget
                                                              .getMindMap()
                                                              ?.getButtonWidth() ??
                                                          24) +
                                                      widget
                                                              .getLinkOutOffset()
                                                              .abs() *
                                                          2,
                                                ),
                                                padding: EdgeInsets.fromLTRB(
                                                  0,
                                                  widget.getLinkOutOffset() >
                                                          0
                                                      ? widget.getLinkOutOffset() *
                                                            2
                                                      : 0,
                                                  0,
                                                  widget.getLinkOutOffset() <
                                                          0
                                                      ? widget
                                                                .getLinkOutOffset()
                                                                .abs() *
                                                            2
                                                      : 0,
                                                ),
                                                child: Container(
                                                  constraints: BoxConstraints(
                                                    maxWidth:
                                                        (widget
                                                                    .getMindMap()
                                                                    ?.getButtonWidth() ??
                                                                24)
                                                            .toDouble(),
                                                    maxHeight:
                                                        (widget
                                                                    .getMindMap()
                                                                    ?.getButtonWidth() ??
                                                                24)
                                                            .toDouble(),
                                                  ),
                                                  decoration: BoxDecoration(
                                                    color:
                                                        widget
                                                            .getMindMap()
                                                            ?.getButtonBackground() ??
                                                        Colors.white,
                                                    borderRadius:
                                                        BorderRadius.circular(
                                                          (widget
                                                                      .getMindMap()
                                                                      ?.getButtonWidth() ??
                                                                  24)
                                                              .toDouble(),
                                                        ),
                                                  ),
                                                  child: IconButton(
                                                    onPressed: () {
                                                      widget
                                                          .getMindMap()
                                                          ?.setSelectedNode(
                                                            widget,
                                                          );
                                                      widget.setExpanded(
                                                        !widget.getExpanded(),
                                                      );
                                                    },
                                                    padding: EdgeInsets.zero,
                                                    icon: Icon(
                                                      widget.getExpanded()
                                                          ? Icons
                                                                .remove_circle_outline
                                                          : Icons
                                                                .add_circle_outline,
                                                      size:
                                                          (widget
                                                                      .getMindMap()
                                                                      ?.getButtonWidth() ??
                                                                  24)
                                                              .toDouble(),
                                                      color:
                                                          widget
                                                              .getMindMap()
                                                              ?.getButtonColor() ??
                                                          Colors.white,
                                                    ),
                                                  ),
                                                ),
                                              ),
                                            ]
                                          : [])
                                    : [
                                        ///left Add Button
                                        Container(
                                          constraints: BoxConstraints(
                                            maxWidth:
                                                (widget
                                                            .getMindMap()
                                                            ?.getButtonWidth() ??
                                                        24)
                                                    .toDouble(),
                                            maxHeight:
                                                (widget
                                                            .getMindMap()
                                                            ?.getButtonWidth() ??
                                                        24)
                                                    .toDouble(),
                                          ),
                                          decoration: BoxDecoration(
                                            color:
                                                (widget
                                                    .getMindMap()
                                                    ?.getButtonBackground() ??
                                                Colors.white),
                                            border: Border.all(
                                              color:
                                                  (widget
                                                      .getMindMap()
                                                      ?.getButtonColor() ??
                                                  Colors.black),
                                              width: 1,
                                            ),
                                            borderRadius: BorderRadius.circular(
                                              (widget
                                                          .getMindMap()
                                                          ?.getButtonWidth() ??
                                                      24)
                                                  .toDouble(),
                                            ),
                                          ),
                                          child: IconButton(
                                            onPressed: () {
                                              widget._focusNode.unfocus();
                                              widget.addLeftChildNode();
                                            },
                                            padding: EdgeInsets.zero,
                                            hoverColor: Colors.green.shade200,
                                            highlightColor: Colors.green,
                                            icon: Icon(
                                              Icons.add_rounded,
                                              size:
                                                  (widget
                                                          .getMindMap()
                                                          ?.getButtonWidth() ??
                                                      24) -
                                                  6,
                                              color:
                                                  (widget
                                                      .getMindMap()
                                                      ?.getButtonColor() ??
                                                  Colors.black),
                                            ),
                                          ),
                                        ),

                                        ///Sapce
                                        widget.getNodeType() ==
                                                    NodeType.root ||
                                                (widget
                                                        .getMindMap()
                                                        ?.getShowRecycle() ??
                                                    false)
                                            ? SizedBox(width: 0, height: 0)
                                            : SizedBox(width: 6),

                                        ///left Delete Button
                                        widget.getNodeType() ==
                                                    NodeType.root ||
                                                (widget
                                                        .getMindMap()
                                                        ?.getShowRecycle() ??
                                                    false)
                                            ? SizedBox(width: 0, height: 0)
                                            : Container(
                                                constraints: BoxConstraints(
                                                  maxWidth:
                                                      (widget
                                                                  .getMindMap()
                                                                  ?.getButtonWidth() ??
                                                              24)
                                                          .toDouble(),
                                                  maxHeight:
                                                      (widget
                                                                  .getMindMap()
                                                                  ?.getButtonWidth() ??
                                                              24)
                                                          .toDouble(),
                                                ),
                                                decoration: BoxDecoration(
                                                  color:
                                                      (widget
                                                          .getMindMap()
                                                          ?.getButtonBackground() ??
                                                      Colors.white),
                                                  border: Border.all(
                                                    color:
                                                        (widget
                                                            .getMindMap()
                                                            ?.getButtonColor() ??
                                                        Colors.black),
                                                    width: 1,
                                                  ),
                                                  borderRadius:
                                                      BorderRadius.circular(
                                                        (widget
                                                                    .getMindMap()
                                                                    ?.getButtonWidth() ??
                                                                24)
                                                            .toDouble(),
                                                      ),
                                                ),
                                                child: IconButton(
                                                  onPressed: () {
                                                    showDialog(
                                                      context: context,
                                                      builder: (context) {
                                                        return AlertDialog(
                                                          content: Text(
                                                            widget
                                                                    .getMindMap()
                                                                    ?.getDeleteNodeString() ??
                                                                "Delete this node?",
                                                          ),
                                                          actions: [
                                                            TextButton(
                                                              child: Text(
                                                                widget
                                                                        .getMindMap()
                                                                        ?.getCancelString() ??
                                                                    "Cancel",
                                                              ),
                                                              onPressed: () {
                                                                Navigator.of(
                                                                  context,
                                                                ).pop();
                                                              },
                                                            ),
                                                            TextButton(
                                                              child: Text(
                                                                widget
                                                                        .getMindMap()
                                                                        ?.getOkString() ??
                                                                    "OK",
                                                              ),
                                                              onPressed: () {
                                                                widget
                                                                    .getParentNode()
                                                                    ?.removeLeftItem(
                                                                      widget,
                                                                    );
                                                                widget
                                                                    .getMindMap()
                                                                    ?.onChanged();
                                                                Navigator.of(
                                                                  context,
                                                                ).pop();
                                                              },
                                                            ),
                                                          ],
                                                        );
                                                      },
                                                    );
                                                  },
                                                  hoverColor:
                                                      Colors.red.shade200,
                                                  highlightColor: Colors.red,
                                                  padding: EdgeInsets.zero,
                                                  icon: Icon(
                                                    Icons.close_rounded,
                                                    size:
                                                        (widget
                                                                .getMindMap()
                                                                ?.getButtonWidth() ??
                                                            24) -
                                                        6,
                                                    color:
                                                        (widget
                                                            .getMindMap()
                                                            ?.getButtonColor() ??
                                                        Colors.black),
                                                  ),
                                                ),
                                              ),

                                        ///Space
                                        !(widget
                                                        .getMindMap()
                                                        ?.hasTextField() ??
                                                    true) &&
                                                (widget
                                                        .getMindMap()
                                                        ?.hasEditButton() ??
                                                    false)
                                            ? SizedBox(width: 6)
                                            : SizedBox(width: 0),

                                        ///Edit Button
                                        !(widget
                                                        .getMindMap()
                                                        ?.hasTextField() ??
                                                    true) &&
                                                (widget
                                                        .getMindMap()
                                                        ?.hasEditButton() ??
                                                    false)
                                            ? Container(
                                                constraints: BoxConstraints(
                                                  maxWidth:
                                                      (widget
                                                                  .getMindMap()
                                                                  ?.getButtonWidth() ??
                                                              24)
                                                          .toDouble(),
                                                  maxHeight:
                                                      (widget
                                                                  .getMindMap()
                                                                  ?.getButtonWidth() ??
                                                              24)
                                                          .toDouble(),
                                                ),
                                                decoration: BoxDecoration(
                                                  color:
                                                      (widget
                                                          .getMindMap()
                                                          ?.getButtonBackground() ??
                                                      Colors.white),
                                                  border: Border.all(
                                                    color:
                                                        (widget
                                                            .getMindMap()
                                                            ?.getButtonColor() ??
                                                        Colors.black),
                                                    width: 1,
                                                  ),
                                                  borderRadius:
                                                      BorderRadius.circular(
                                                        (widget
                                                                    .getMindMap()
                                                                    ?.getButtonWidth() ??
                                                                24)
                                                            .toDouble(),
                                                      ),
                                                ),
                                                child: IconButton(
                                                  onPressed: () {
                                                    widget
                                                        .getMindMap()
                                                        ?.onEdit(widget);
                                                  },
                                                  hoverColor:
                                                      Colors.blue.shade200,
                                                  highlightColor: Colors.blue,
                                                  padding: EdgeInsets.zero,
                                                  icon: Icon(
                                                    Icons.edit_outlined,
                                                    size:
                                                        (widget
                                                                .getMindMap()
                                                                ?.getButtonWidth() ??
                                                            24) -
                                                        8,
                                                    color:
                                                        (widget
                                                            .getMindMap()
                                                            ?.getButtonColor() ??
                                                        Colors.black),
                                                  ),
                                                ),
                                              )
                                            : SizedBox(width: 0, height: 0),
                                      ])
                              : (widget.getReadOnly()
                                    ? (widget.getNodeType() ==
                                                  NodeType.left &&
                                              widget.canExpand() &&
                                              !widget.getExpanded() &&
                                              widget
                                                  .getLeftItems()
                                                  .isNotEmpty &&
                                              (widget
                                                          .getMindMap()
                                                          ?.getExpandedLevel() ??
                                                      0) <=
                                                  widget.getLevel() + 1
                                          ? [
                                              ///Left Expand Button
                                              Container(
                                                constraints: BoxConstraints(
                                                  maxHeight:
                                                      (widget
                                                              .getMindMap()
                                                              ?.getButtonWidth() ??
                                                          24) +
                                                      widget
                                                              .getLinkOutOffset()
                                                              .abs() *
                                                          2,
                                                ),
                                                padding: EdgeInsets.fromLTRB(
                                                  0,
                                                  widget.getLinkOutOffset() >
                                                          0
                                                      ? widget.getLinkOutOffset() *
                                                            2
                                                      : 0,
                                                  0,
                                                  widget.getLinkOutOffset() <
                                                          0
                                                      ? widget
                                                                .getLinkOutOffset()
                                                                .abs() *
                                                            2
                                                      : 0,
                                                ),
                                                child: Container(
                                                  constraints: BoxConstraints(
                                                    maxWidth:
                                                        (widget
                                                                    .getMindMap()
                                                                    ?.getButtonWidth() ??
                                                                24)
                                                            .toDouble(),
                                                    maxHeight:
                                                        (widget
                                                                    .getMindMap()
                                                                    ?.getButtonWidth() ??
                                                                24)
                                                            .toDouble(),
                                                  ),
                                                  decoration: BoxDecoration(
                                                    color:
                                                        (widget
                                                            .getMindMap()
                                                            ?.getButtonBackground() ??
                                                        Colors.white),
                                                    borderRadius:
                                                        BorderRadius.circular(
                                                          (widget
                                                                      .getMindMap()
                                                                      ?.getButtonWidth() ??
                                                                  24)
                                                              .toDouble(),
                                                        ),
                                                  ),
                                                  child: IconButton(
                                                    onPressed: () {
                                                      widget
                                                          .getMindMap()
                                                          ?.setSelectedNode(
                                                            widget,
                                                          );
                                                      widget.setExpanded(
                                                        !widget.getExpanded(),
                                                      );
                                                    },
                                                    padding: EdgeInsets.zero,
                                                    icon: Icon(
                                                      Icons
                                                          .add_circle_outline,
                                                      size:
                                                          (widget
                                                                      .getMindMap()
                                                                      ?.getButtonWidth() ??
                                                                  24)
                                                              .toDouble(),
                                                      color:
                                                          (widget
                                                              .getMindMap()
                                                              ?.getButtonColor() ??
                                                          Colors.black),
                                                    ),
                                                  ),
                                                ),
                                              ),
                                            ]
                                          : [])
                                    : [])),
                        ],
                      ),
                    ),
                  ]
                : []),

            ///Node
            MindMapNodeTitle(node: widget),

            ///RightSpace
            ...(widget.getNodeType() != NodeType.left
                ? [
                    Container(
                      constraints: BoxConstraints(
                        minWidth: widget.getHSpace().toDouble(),
                        maxWidth: widget.getHSpace().toDouble(),
                        minHeight:
                            (widget.getMindMap()?.getButtonWidth() ?? 24)
                                .toDouble(),
                      ),
                      padding: EdgeInsets.fromLTRB(3, 0, 3, 0),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.start,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: [
                          ...(widget.getSelected()
                              ? (widget.getReadOnly()
                                    ? (widget.getNodeType() ==
                                                  NodeType.right &&
                                              widget.canExpand() &&
                                              widget
                                                  .getRightItems()
                                                  .isNotEmpty &&
                                              (widget
                                                          .getMindMap()
                                                          ?.getExpandedLevel() ??
                                                      0) <=
                                                  widget.getLevel() + 1
                                          ? [
                                              ///Right Expand Button
                                              Container(
                                                constraints: BoxConstraints(
                                                  maxHeight:
                                                      (widget
                                                              .getMindMap()
                                                              ?.getButtonWidth() ??
                                                          24) +
                                                      widget
                                                              .getLinkOutOffset()
                                                              .abs() *
                                                          2,
                                                ),
                                                padding: EdgeInsets.fromLTRB(
                                                  0,
                                                  widget.getLinkOutOffset() >
                                                          0
                                                      ? widget.getLinkOutOffset() *
                                                            2
                                                      : 0,
                                                  0,
                                                  widget.getLinkOutOffset() <
                                                          0
                                                      ? widget
                                                                .getLinkOutOffset()
                                                                .abs() *
                                                            2
                                                      : 0,
                                                ),
                                                child: Container(
                                                  constraints: BoxConstraints(
                                                    maxWidth:
                                                        (widget
                                                                    .getMindMap()
                                                                    ?.getButtonWidth() ??
                                                                24)
                                                            .toDouble(),
                                                    maxHeight:
                                                        (widget
                                                                    .getMindMap()
                                                                    ?.getButtonWidth() ??
                                                                24)
                                                            .toDouble(),
                                                  ),
                                                  decoration: BoxDecoration(
                                                    color:
                                                        (widget
                                                            .getMindMap()
                                                            ?.getButtonBackground() ??
                                                        Colors.white),
                                                    borderRadius:
                                                        BorderRadius.circular(
                                                          (widget
                                                                      .getMindMap()
                                                                      ?.getButtonWidth() ??
                                                                  24)
                                                              .toDouble(),
                                                        ),
                                                  ),
                                                  child: IconButton(
                                                    onPressed: () {
                                                      widget
                                                          .getMindMap()
                                                          ?.setSelectedNode(
                                                            widget,
                                                          );
                                                      widget.setExpanded(
                                                        !widget.getExpanded(),
                                                      );
                                                    },
                                                    padding: EdgeInsets.zero,
                                                    icon: Icon(
                                                      widget.getExpanded()
                                                          ? Icons
                                                                .remove_circle_outline
                                                          : Icons
                                                                .add_circle_outline,
                                                      size:
                                                          (widget
                                                                      .getMindMap()
                                                                      ?.getButtonWidth() ??
                                                                  24)
                                                              .toDouble(),
                                                      color:
                                                          (widget
                                                              .getMindMap()
                                                              ?.getButtonColor() ??
                                                          Colors.black),
                                                    ),
                                                  ),
                                                ),
                                              ),
                                            ]
                                          : [])
                                    : [
                                        ///Edit Button
                                        !(widget
                                                        .getMindMap()
                                                        ?.hasTextField() ??
                                                    true) &&
                                                (widget
                                                        .getMindMap()
                                                        ?.hasEditButton() ??
                                                    false)
                                            ? Container(
                                                constraints: BoxConstraints(
                                                  maxWidth:
                                                      (widget
                                                                  .getMindMap()
                                                                  ?.getButtonWidth() ??
                                                              24)
                                                          .toDouble(),
                                                  maxHeight:
                                                      (widget
                                                                  .getMindMap()
                                                                  ?.getButtonWidth() ??
                                                              24)
                                                          .toDouble(),
                                                ),
                                                decoration: BoxDecoration(
                                                  color:
                                                      (widget
                                                          .getMindMap()
                                                          ?.getButtonBackground() ??
                                                      Colors.white),
                                                  border: Border.all(
                                                    color:
                                                        (widget
                                                            .getMindMap()
                                                            ?.getButtonColor() ??
                                                        Colors.black),
                                                    width: 1,
                                                  ),
                                                  borderRadius:
                                                      BorderRadius.circular(
                                                        (widget
                                                                    .getMindMap()
                                                                    ?.getButtonWidth() ??
                                                                24)
                                                            .toDouble(),
                                                      ),
                                                ),
                                                child: IconButton(
                                                  onPressed: () {
                                                    widget
                                                        .getMindMap()
                                                        ?.onEdit(widget);
                                                  },
                                                  hoverColor:
                                                      Colors.blue.shade200,
                                                  highlightColor: Colors.blue,
                                                  padding: EdgeInsets.zero,
                                                  icon: Icon(
                                                    Icons.edit_outlined,
                                                    size:
                                                        (widget
                                                                .getMindMap()
                                                                ?.getButtonWidth() ??
                                                            24) -
                                                        8,
                                                    color:
                                                        (widget
                                                            .getMindMap()
                                                            ?.getButtonColor() ??
                                                        Colors.black),
                                                  ),
                                                ),
                                              )
                                            : SizedBox(width: 0, height: 0),

                                        ///Space
                                        !(widget
                                                        .getMindMap()
                                                        ?.hasTextField() ??
                                                    true) &&
                                                (widget
                                                        .getMindMap()
                                                        ?.hasEditButton() ??
                                                    false)
                                            ? SizedBox(width: 6)
                                            : SizedBox(width: 0),

                                        ///Right Delete Button
                                        widget.getNodeType() ==
                                                    NodeType.root ||
                                                (widget
                                                        .getMindMap()
                                                        ?.getShowRecycle() ??
                                                    false)
                                            ? SizedBox(width: 0, height: 0)
                                            : Container(
                                                constraints: BoxConstraints(
                                                  maxWidth:
                                                      (widget
                                                                  .getMindMap()
                                                                  ?.getButtonWidth() ??
                                                              24)
                                                          .toDouble(),
                                                  maxHeight:
                                                      (widget
                                                                  .getMindMap()
                                                                  ?.getButtonWidth() ??
                                                              24)
                                                          .toDouble(),
                                                ),
                                                decoration: BoxDecoration(
                                                  color:
                                                      (widget
                                                          .getMindMap()
                                                          ?.getButtonBackground() ??
                                                      Colors.white),
                                                  border: Border.all(
                                                    color:
                                                        (widget
                                                            .getMindMap()
                                                            ?.getButtonColor() ??
                                                        Colors.black),
                                                    width: 1,
                                                  ),
                                                  borderRadius:
                                                      BorderRadius.circular(
                                                        (widget
                                                                    .getMindMap()
                                                                    ?.getButtonWidth() ??
                                                                24)
                                                            .toDouble(),
                                                      ),
                                                ),
                                                child: IconButton(
                                                  onPressed: () {
                                                    showDialog(
                                                      context: context,
                                                      builder: (context) {
                                                        return AlertDialog(
                                                          content: Text(
                                                            widget
                                                                    .getMindMap()
                                                                    ?.getDeleteNodeString() ??
                                                                "Delete this node?",
                                                          ),
                                                          actions: [
                                                            TextButton(
                                                              child: Text(
                                                                widget
                                                                        .getMindMap()
                                                                        ?.getCancelString() ??
                                                                    "Cancel",
                                                              ),
                                                              onPressed: () {
                                                                Navigator.of(
                                                                  context,
                                                                ).pop();
                                                              },
                                                            ),
                                                            TextButton(
                                                              child: Text(
                                                                widget
                                                                        .getMindMap()
                                                                        ?.getOkString() ??
                                                                    "OK",
                                                              ),
                                                              onPressed: () {
                                                                widget
                                                                    .getParentNode()
                                                                    ?.removeRightItem(
                                                                      widget,
                                                                    );
                                                                widget
                                                                    .getMindMap()
                                                                    ?.onChanged();
                                                                Navigator.of(
                                                                  context,
                                                                ).pop();
                                                              },
                                                            ),
                                                          ],
                                                        );
                                                      },
                                                    );
                                                  },
                                                  hoverColor:
                                                      Colors.red.shade200,
                                                  highlightColor: Colors.red,
                                                  padding: EdgeInsets.zero,
                                                  icon: Icon(
                                                    Icons.close_rounded,
                                                    size:
                                                        (widget
                                                                .getMindMap()
                                                                ?.getButtonWidth() ??
                                                            24) -
                                                        6,
                                                    color:
                                                        (widget
                                                            .getMindMap()
                                                            ?.getButtonColor() ??
                                                        Colors.black),
                                                  ),
                                                ),
                                              ),

                                        ///Sapce
                                        widget.getNodeType() ==
                                                    NodeType.root ||
                                                (widget
                                                        .getMindMap()
                                                        ?.getShowRecycle() ??
                                                    false)
                                            ? SizedBox(width: 0, height: 0)
                                            : SizedBox(width: 6),

                                        ///Right add Button
                                        Container(
                                          constraints: BoxConstraints(
                                            maxWidth:
                                                (widget
                                                            .getMindMap()
                                                            ?.getButtonWidth() ??
                                                        24)
                                                    .toDouble(),
                                            maxHeight:
                                                (widget
                                                            .getMindMap()
                                                            ?.getButtonWidth() ??
                                                        24)
                                                    .toDouble(),
                                          ),
                                          decoration: BoxDecoration(
                                            color:
                                                (widget
                                                    .getMindMap()
                                                    ?.getButtonBackground() ??
                                                Colors.white),
                                            border: Border.all(
                                              color:
                                                  (widget
                                                      .getMindMap()
                                                      ?.getButtonColor() ??
                                                  Colors.black),
                                              width: 1,
                                            ),
                                            borderRadius: BorderRadius.circular(
                                              (widget
                                                          .getMindMap()
                                                          ?.getButtonWidth() ??
                                                      24)
                                                  .toDouble(),
                                            ),
                                          ),
                                          child: IconButton(
                                            onPressed: () {
                                              widget._focusNode.unfocus();
                                              widget.addRightChildNode();
                                            },
                                            padding: EdgeInsets.zero,
                                            hoverColor: Colors.green.shade200,
                                            highlightColor: Colors.green,
                                            icon: Icon(
                                              Icons.add_rounded,
                                              size:
                                                  (widget
                                                          .getMindMap()
                                                          ?.getButtonWidth() ??
                                                      24) -
                                                  6,
                                              color:
                                                  (widget
                                                      .getMindMap()
                                                      ?.getButtonColor() ??
                                                  Colors.black),
                                            ),
                                          ),
                                        ),
                                      ])
                              : (widget.getReadOnly()
                                    ? (widget.getNodeType() ==
                                                  NodeType.right &&
                                              widget.canExpand() &&
                                              !widget.getExpanded() &&
                                              widget
                                                  .getRightItems()
                                                  .isNotEmpty &&
                                              (widget
                                                          .getMindMap()
                                                          ?.getExpandedLevel() ??
                                                      0) <=
                                                  widget.getLevel() + 1
                                          ? [
                                              ///Right Expand Button
                                              Container(
                                                constraints: BoxConstraints(
                                                  maxHeight:
                                                      (widget
                                                              .getMindMap()
                                                              ?.getButtonWidth() ??
                                                          24) +
                                                      widget
                                                              .getLinkOutOffset()
                                                              .abs() *
                                                          2,
                                                ),
                                                padding: EdgeInsets.fromLTRB(
                                                  0,
                                                  widget.getLinkOutOffset() >
                                                          0
                                                      ? widget.getLinkOutOffset() *
                                                            2
                                                      : 0,
                                                  0,
                                                  widget.getLinkOutOffset() <
                                                          0
                                                      ? widget
                                                                .getLinkOutOffset()
                                                                .abs() *
                                                            2
                                                      : 0,
                                                ),
                                                child: Container(
                                                  constraints: BoxConstraints(
                                                    maxWidth:
                                                        (widget
                                                                    .getMindMap()
                                                                    ?.getButtonWidth() ??
                                                                24)
                                                            .toDouble(),
                                                    maxHeight:
                                                        (widget
                                                                    .getMindMap()
                                                                    ?.getButtonWidth() ??
                                                                24)
                                                            .toDouble(),
                                                  ),
                                                  decoration: BoxDecoration(
                                                    color:
                                                        (widget
                                                            .getMindMap()
                                                            ?.getButtonBackground() ??
                                                        Colors.white),
                                                    borderRadius:
                                                        BorderRadius.circular(
                                                          (widget
                                                                      .getMindMap()
                                                                      ?.getButtonWidth() ??
                                                                  24)
                                                              .toDouble(),
                                                        ),
                                                  ),
                                                  child: IconButton(
                                                    onPressed: () {
                                                      widget
                                                          .getMindMap()
                                                          ?.setSelectedNode(
                                                            widget,
                                                          );
                                                      widget.setExpanded(
                                                        !widget.getExpanded(),
                                                      );
                                                    },
                                                    padding: EdgeInsets.zero,
                                                    icon: Icon(
                                                      Icons
                                                          .add_circle_outline,
                                                      size:
                                                          (widget
                                                                      .getMindMap()
                                                                      ?.getButtonWidth() ??
                                                                  24)
                                                              .toDouble(),
                                                      color:
                                                          (widget
                                                              .getMindMap()
                                                              ?.getButtonColor() ??
                                                          Colors.black),
                                                    ),
                                                  ),
                                                ),
                                              ),
                                            ]
                                          : [])
                                    : [])),
                        ],
                      ),
                    ),
                  ]
                : []),

            ///Right Items
            ...(rightItems.isEmpty ||
                    (!widget.getExpanded() &&
                        (widget.getMindMap()?.getReadOnly() ?? false))
                ? []
                : [
                    Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisSize: MainAxisSize.min,
                      spacing: widget.getVSpace().toDouble(),
                      children: rightItems,
                    ),
                  ]),
          ],
        ),
      );
    case MapType.fishbone:
      if (widget.getNodeType() == NodeType.root) {
        double maxHeight = 0;

        double maxWidth = 0;
        if (widget.getLeftItems().isEmpty && widget.getRightItems().isEmpty) {
          maxWidth =
              maxWidth +
              (widget.getSize()?.width ?? 0) +
              widget.getHSpace() +
              (widget.getMindMap()?.getButtonWidth() ?? 0) +
              12 +
              widget.getImage2Width();
          maxHeight =
              (widget.getSize()?.height ?? 0) + widget.getVSpace() * 2;
        } else {
          if (widget.getMindMap()?.getFishboneMapType() ==
              FishboneMapType.leftToRight) {
            List<List<IMindMapNode>> items = [];
            List<IMindMapNode> c = [];
            for (var item in widget.getRightItems()) {
              if (maxHeight <
                  (item.getSize()?.height ?? 0) +
                      item.getFishboneHeight() +
                      widget.getVSpace().toDouble()) {
                maxHeight =
                    (item.getSize()?.height ?? 0) +
                    item.getFishboneHeight() +
                    widget.getVSpace().toDouble();
              }
              c.add(item);
              if (c.length >= 2) {
                items.add(c);
                c = [];
              }
            }
            for (
              int index = 0;
              index < widget.getLeftItems().length;
              index++
            ) {
              var item = widget
                  .getLeftItems()[widget.getLeftItems().length - index - 1];
              if (maxHeight <
                  (item.getSize()?.height ?? 0) +
                      item.getFishboneHeight() +
                      widget.getVSpace().toDouble()) {
                maxHeight =
                    (item.getSize()?.height ?? 0) +
                    item.getFishboneHeight() +
                    widget.getVSpace().toDouble();
              }
              c.add(item);
              if (c.length >= 2) {
                items.add(c);
                c = [];
              }
            }
            if (c.isNotEmpty) {
              items.add(c);
            }
            maxWidth += (widget.getSize()?.width ?? 0) + widget.getHSpace();
            for (List<IMindMapNode> item in items) {
              double d1 =
                  item[0].getFishboneWidth() +
                  (item[0].getSize()?.width ?? 0) / 2;
              double d2 = item.length <= 1
                  ? 0
                  : item[1].getFishboneWidth() +
                        (item[1].getSize()?.width ?? 0) / 2 +
                        widget.getHSpace();

              maxWidth += d1 < d2 ? d2 : d1;
              maxWidth += widget.getHSpace();
              if (item == items.last) {
                double w1 =
                    item[0].getFishboneWidth() +
                    item[0].getFishbonePosition().dx +
                    (item[0].getSize()?.width ?? 0) / 2;
                maxWidth = maxWidth < w1 ? w1 : maxWidth;
              }
              if (item.length > 1) {
                double w1 =
                    item[1].getFishboneWidth() +
                    item[1].getFishbonePosition().dx +
                    (item[1].getSize()?.width ?? 0) / 2;
                maxWidth = maxWidth < w1 ? w1 : maxWidth;
              }
            }
          } else {
            List<List<IMindMapNode>> items = [];
            List<IMindMapNode> c = [];
            for (var item in widget.getLeftItems()) {
              if (maxHeight <
                  (item.getSize()?.height ?? 0) +
                      item.getFishboneHeight() +
                      widget.getVSpace().toDouble()) {
                maxHeight =
                    (item.getSize()?.height ?? 0) +
                    item.getFishboneHeight() +
                    widget.getVSpace().toDouble();
              }
              c.add(item);
              if (c.length >= 2) {
                items.add(c);
                c = [];
              }
            }
            for (
              int index = 0;
              index < widget.getRightItems().length;
              index++
            ) {
              var item = widget
                  .getRightItems()[widget.getRightItems().length - index - 1];
              if (maxHeight <
                  (item.getSize()?.height ?? 0) +
                      item.getFishboneHeight() +
                      widget.getVSpace().toDouble()) {
                maxHeight =
                    (item.getSize()?.height ?? 0) +
                    item.getFishboneHeight() +
                    widget.getVSpace().toDouble();
              }
              c.add(item);
              if (c.length >= 2) {
                items.add(c);
                c = [];
              }
            }
            if (c.isNotEmpty) {
              items.add(c);
            }
            maxWidth += (widget.getSize()?.width ?? 0) + widget.getHSpace();
            for (List<IMindMapNode> item in items) {
              double d1 =
                  item[0].getFishboneWidth() +
                  (item[0].getSize()?.width ?? 0) / 2;
              double d2 = item.length <= 1
                  ? 0
                  : item[1].getFishboneWidth() +
                        (item[1].getSize()?.width ?? 0) / 2 +
                        widget.getHSpace();

              maxWidth += d1 < d2 ? d2 : d1;
              maxWidth += widget.getHSpace();
              if (item == items.last) {
                double w1 =
                    (widget
                            .getMindMap()
                            ?.getRootNode()
                            .getFishbonePosition()
                            .dx ??
                        0) -
                    (item[0].getFishbonePosition().dx +
                        (item[0].getSize()?.width ?? 0) / 2 -
                        item[0].getFishboneWidth()) +
                    (widget.getMindMap()?.getRootNode().getSize()?.width ??
                        0);
                maxWidth = maxWidth < w1 ? w1 : maxWidth;
              }
              if (item.length > 1) {
                double w1 =
                    (widget
                            .getMindMap()
                            ?.getRootNode()
                            .getFishbonePosition()
                            .dx ??
                        0) -
                    (item[1].getFishbonePosition().dx +
                        (item[1].getSize()?.width ?? 0) / 2 -
                        item[1].getFishboneWidth()) +
                    (widget.getMindMap()?.getRootNode().getSize()?.width ??
                        0);
                maxWidth = maxWidth < w1 ? w1 : maxWidth;
              }
            }
          }
        }
        List<Widget> list = [];

        widget.setFishbonePosition(
          Offset(
            widget.getMindMap()?.getFishboneMapType() ==
                    FishboneMapType.rightToLeft
                ? maxWidth -
                      (widget.getSize()?.width ?? 0) -
                      (widget.getBorder() as Border).right.width
                : (widget.getBorder() as Border).left.width,
            maxHeight -
                (widget.getSize()?.height ?? 0) / 2 +
                widget.getLinkWidth() / 2,
          ),
        );

        list.add(
          Positioned(
            left:
                widget.getMindMap()?.getFishboneMapType() ==
                    FishboneMapType.rightToLeft
                ? maxWidth -
                      (widget.getSize()?.width ?? 0) -
                      (widget.getBorder() as Border).right.width
                : (widget.getBorder() as Border).left.width,
            top:
                maxHeight -
                (widget.getSize()?.height ?? 0) / 2 +
                widget.getLinkWidth() / 2,
            child: MindMapNodeTitle(node: widget),
          ),
        );

        list.addAll(getFinshboneNodes(widget, maxWidth, maxHeight));

        if (widget.image2 != null) {
          list.add(
            Positioned(
              left:
                  widget.getMindMap()?.getFishboneMapType() ==
                      FishboneMapType.rightToLeft
                  ? 0
                  : maxWidth - widget.getImage2Width(),
              top:
                  maxHeight +
                  widget.getLinkWidth() / 2 -
                  widget.getImage2Height() / 2,
              child:
                  widget.getMindMap()?.getFishboneMapType() ==
                      FishboneMapType.leftToRight
                  ? Transform.flip(
                      flipX: true,
                      child: Image.memory(
                        widget.image2!,
                        width: widget.getImage2Width(),
                        height: widget.getImage2Height(),
                        fit: BoxFit.fill,
                      ),
                    )
                  : Image.memory(
                      widget.image2!,
                      width: widget.getImage2Width(),
                      height: widget.getImage2Height(),
                      fit: BoxFit.fill,
                    ),
            ),
          );
        }
        widget.getMindMap()?.setFishboneSize(Size(maxWidth, maxHeight * 2));
        if (widget.getMindMap()?.getSelectedNode() != null) {
          list.addAll(
            getSelectedNodesButtons(widget.getMindMap()!.getSelectedNode()!),
          );
        }
        return SizedBox(
          width: maxWidth,
          height: maxHeight * 2 + widget.getLinkWidth(),
          child: Stack(children: list),
        );
      } else {
        return MindMapNodeTitle(node: widget);
      }
  }
}