getBody method
Implementation
Widget getBody(bool hasAppBar) {
// ignore safe area is only applicable if we don't have an AppBar
bool _useSafeArea = !hasAppBar && useSafeArea();
if (widget._pageModel.menu is SidebarMenu) {
SidebarMenu sidebarMenu = widget._pageModel.menu as SidebarMenu;
List<MenuItem> menuItems = sidebarMenu.menuItems;
List<NavigationRailDestination> navItems = [];
for (int i = 0; i < menuItems.length; i++) {
MenuItem item = menuItems[i];
navItems.add(NavigationRailDestination(
padding: Utils.getInsets(sidebarMenu.runtimeStyles?['itemPadding']),
icon: item.icon != null
? ensemble.Icon.fromModel(item.icon!)
: const SizedBox.shrink(),
label: Text(Utils.translate(item.label ?? '', context))));
}
// TODO: consolidate buildWidget into 1 place
double paddingFromSafeSpace = 15;
Widget? headerWidget;
if (sidebarMenu.headerModel != null) {
headerWidget = _scopeManager.buildWidget(sidebarMenu.headerModel!);
}
Widget menuHeader = Column(children: [
SizedBox(height: paddingFromSafeSpace),
Container(
child: headerWidget,
)
]);
Widget? menuFooter;
if (sidebarMenu.footerModel != null) {
// push footer to the bottom of the rail
menuFooter = Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: _scopeManager.buildWidget(sidebarMenu.footerModel!)),
);
}
MenuItemDisplay itemDisplay = MenuItemDisplay.values
.from(sidebarMenu.runtimeStyles?['itemDisplay']) ??
MenuItemDisplay.stacked;
// stacked's min gap seems to be 72 regardless of what we set. For side by side optimal min gap is around 40
// we set this minGap and let user controls with itemPadding
int minGap = itemDisplay == MenuItemDisplay.sideBySide ? 40 : 72;
// minExtendedWidth is applicable only for side by side, and should never be below minWidth (or exception)
int minWidth = Utils.optionalInt(sidebarMenu.runtimeStyles?['minWidth'],
min: minGap) ??
200;
List<Widget> content = [];
// process menu styles
Color? menuBackground =
Utils.getColor(sidebarMenu.runtimeStyles?['backgroundColor']);
content.add(NavigationRail(
extended: itemDisplay == MenuItemDisplay.sideBySide ? true : false,
minExtendedWidth: minWidth.toDouble(),
minWidth: minGap.toDouble(),
// this is important for optimal default item spacing
labelType: itemDisplay != MenuItemDisplay.sideBySide
? NavigationRailLabelType.all
: null,
backgroundColor: menuBackground,
leading: menuHeader,
destinations: navItems,
trailing: menuFooter,
selectedIndex: selectedPage,
onDestinationSelected: (index) =>
selectNavigationIndex(context, menuItems[index]),
));
// show a divider between the NavigationRail and the content
Color? borderColor =
Utils.getColor(widget._pageModel.menu!.runtimeStyles?['borderColor']);
int? borderWidth = Utils.optionalInt(
widget._pageModel.menu!.runtimeStyles?['borderWidth']);
if (borderColor != null || borderWidth != null) {
content.add(VerticalDivider(
thickness: (borderWidth ?? 1).toDouble(),
width: (borderWidth ?? 1).toDouble(),
color: borderColor));
}
// add the bodyWidget
content.add(Expanded(
child: SafeArea(
top: _useSafeArea, bottom: _useSafeArea, child: rootWidget)));
return DefaultTextStyle.merge(
style: widget._controller._textStyle?.getTextStyle(),
maxLines: widget._controller.maxLines,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start, children: content));
}
return DefaultTextStyle.merge(
style: widget._controller._textStyle?.getTextStyle(),
maxLines: widget._controller.maxLines,
child: SafeArea(
top: _useSafeArea, bottom: _useSafeArea, child: rootWidget));
}