build method

Widget build(
  1. BuildContext context,
  2. bool selected,
  3. VoidCallback? onPressed, {
  4. PaneDisplayMode? displayMode,
  5. bool showTextOnTop = true,
  6. int? itemIndex,
  7. bool? autofocus,
})

Used to construct the pane items all around NavigationView. You can customize how the pane items should look like by overriding this method

Implementation

Widget build(
  BuildContext context,
  bool selected,
  VoidCallback? onPressed, {
  PaneDisplayMode? displayMode,
  bool showTextOnTop = true,
  int? itemIndex,
  bool? autofocus,
}) {
  final maybeBody = _InheritedNavigationView.maybeOf(context);
  final mode = displayMode ??
      maybeBody?.displayMode ??
      maybeBody?.pane?.displayMode ??
      PaneDisplayMode.minimal;
  assert(mode != PaneDisplayMode.auto);
  assert(debugCheckHasFluentTheme(context));

  final isTransitioning = maybeBody?.isTransitioning ?? false;

  final theme = NavigationPaneTheme.of(context);
  final titleText = title?.getProperty<String>() ?? '';

  final baseStyle = title?.getProperty<TextStyle>() ?? const TextStyle();

  final isTop = mode == PaneDisplayMode.top;
  final isMinimal = mode == PaneDisplayMode.minimal;
  final isCompact = mode == PaneDisplayMode.compact;

  final onItemTapped =
      (onPressed == null && onTap == null) || !enabled || isTransitioning
          ? null
          : () {
              onPressed?.call();
              onTap?.call();
            };

  final button = HoverButton(
    autofocus: autofocus ?? this.autofocus,
    focusNode: focusNode,
    onPressed: onItemTapped,
    cursor: mouseCursor,
    focusEnabled: isMinimal ? (maybeBody?.minimalPaneOpen ?? false) : true,
    forceEnabled: enabled,
    builder: (context, states) {
      var textStyle = () {
        var style = !isTop
            ? (selected
                ? theme.selectedTextStyle?.resolve(states)
                : theme.unselectedTextStyle?.resolve(states))
            : (selected
                ? theme.selectedTopTextStyle?.resolve(states)
                : theme.unselectedTopTextStyle?.resolve(states));
        if (style == null) return baseStyle;
        return style.merge(baseStyle);
      }();

      final textResult = titleText.isNotEmpty
          ? Padding(
              padding: theme.labelPadding ?? EdgeInsets.zero,
              child: RichText(
                text: title!.getProperty<InlineSpan>(textStyle)!,
                maxLines: 1,
                overflow: TextOverflow.fade,
                softWrap: false,
                textAlign: title?.getProperty<TextAlign>() ?? TextAlign.start,
                textHeightBehavior: title?.getProperty<TextHeightBehavior>(),
                textWidthBasis: title?.getProperty<TextWidthBasis>() ??
                    TextWidthBasis.parent,
              ),
            )
          : const SizedBox.shrink();
      Widget result() {
        final iconThemeData = IconThemeData(
          color: textStyle.color ??
              (selected
                  ? theme.selectedIconColor?.resolve(states)
                  : theme.unselectedIconColor?.resolve(states)),
          size: textStyle.fontSize ?? 16.0,
        );
        switch (mode) {
          case PaneDisplayMode.compact:
            return Container(
              key: itemKey,
              constraints: const BoxConstraints(
                minHeight: kPaneItemMinHeight,
              ),
              alignment: AlignmentDirectional.center,
              child: Padding(
                padding: theme.iconPadding ?? EdgeInsets.zero,
                child: IconTheme.merge(
                  data: iconThemeData,
                  child: Align(
                    alignment: AlignmentDirectional.centerStart,
                    child: () {
                      if (infoBadge != null) {
                        return Stack(
                          alignment: AlignmentDirectional.center,
                          clipBehavior: Clip.none,
                          children: [
                            icon,
                            PositionedDirectional(
                              end: -8,
                              top: -8,
                              child: infoBadge!,
                            ),
                          ],
                        );
                      }
                      return icon;
                    }(),
                  ),
                ),
              ),
            );
          case PaneDisplayMode.minimal:
          case PaneDisplayMode.open:
            final shouldShowTrailing = !isTransitioning;

            return ConstrainedBox(
              key: itemKey,
              constraints: const BoxConstraints(
                minHeight: kPaneItemMinHeight,
              ),
              child: Row(children: [
                Padding(
                  padding: theme.iconPadding ?? EdgeInsets.zero,
                  child: IconTheme.merge(
                    data: iconThemeData,
                    child: Center(child: icon),
                  ),
                ),
                Expanded(child: textResult),
                if (shouldShowTrailing) ...[
                  if (infoBadge != null)
                    Padding(
                      padding: const EdgeInsetsDirectional.only(end: 8.0),
                      child: infoBadge!,
                    ),
                  if (trailing != null)
                    IconTheme.merge(
                      data: const IconThemeData(size: 16.0),
                      child: trailing!,
                    ),
                ],
              ]),
            );
          case PaneDisplayMode.top:
            Widget result = Row(mainAxisSize: MainAxisSize.min, children: [
              Padding(
                padding: theme.iconPadding ?? EdgeInsets.zero,
                child: IconTheme.merge(
                  data: iconThemeData,
                  child: Center(child: icon),
                ),
              ),
              if (showTextOnTop) textResult,
              if (trailing != null)
                IconTheme.merge(
                  data: const IconThemeData(size: 16.0),
                  child: trailing!,
                ),
            ]);
            if (infoBadge != null) {
              return Stack(key: itemKey, clipBehavior: Clip.none, children: [
                result,
                if (infoBadge != null)
                  PositionedDirectional(
                    end: -3,
                    top: 3,
                    child: infoBadge!,
                  ),
              ]);
            }
            return KeyedSubtree(key: itemKey, child: result);
          default:
            throw '$mode is not a supported type';
        }
      }

      return Semantics(
        label: titleText.isEmpty ? null : titleText,
        selected: selected,
        child: Container(
          margin: const EdgeInsets.symmetric(horizontal: 6.0),
          decoration: BoxDecoration(
            color: () {
              final tileColor = this.tileColor ??
                  theme.tileColor ??
                  kDefaultPaneItemColor(context, isTop);
              final newStates = states.toSet()..remove(ButtonStates.disabled);
              if (selected && selectedTileColor != null) {
                return selectedTileColor!.resolve(newStates);
              }
              return tileColor.resolve(
                selected
                    ? {
                        states.isHovering
                            ? ButtonStates.pressing
                            : ButtonStates.hovering,
                      }
                    : newStates,
              );
            }(),
            borderRadius: BorderRadius.circular(4.0),
          ),
          child: FocusBorder(
            focused: states.isFocused,
            renderOutside: false,
            child: () {
              final showTooltip = ((isTop && !showTextOnTop) || isCompact) &&
                  titleText.isNotEmpty &&
                  !states.isDisabled;

              if (showTooltip) {
                return Tooltip(
                  richMessage: title?.getProperty<InlineSpan>(),
                  style: TooltipThemeData(textStyle: baseStyle),
                  child: result(),
                );
              }

              return result();
            }(),
          ),
        ),
      );
    },
  );

  final index = () {
    if (itemIndex != null) return itemIndex;
    if (maybeBody?.pane?.indicator != null) {
      return maybeBody!.pane!.effectiveIndexOf(this);
    }
  }();

  return Padding(
    key: key,
    padding: const EdgeInsetsDirectional.only(bottom: 4.0),
    child: () {
      // If there is an indicator and the item is an effective item
      if (maybeBody?.pane?.indicator != null &&
          index != null &&
          !index.isNegative) {
        final key = PaneItemKeys.of(index, context);

        return Stack(children: [
          button,
          Positioned.fill(
            child: _InheritedNavigationView.merge(
              currentItemIndex: index,
              currentItemSelected: selected,
              child: KeyedSubtree(
                key: key,
                child: maybeBody!.pane!.indicator!,
              ),
            ),
          ),
        ]);
      }

      return button;
    }(),
  );
}