Skip to content

Commit

Permalink
Rework NavigationPane and NavigationIndicator pt.1 (Fixes #143 )
Browse files Browse the repository at this point in the history
  • Loading branch information
bdlukaa committed Feb 2, 2022
1 parent 3dc3482 commit a5a03a8
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 103 deletions.
67 changes: 67 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,73 @@ Date format: DD/MM/YYYY
- Tests ([#142](https://github.com/bdlukaa/fluent_ui/pull/142))
- Added Material Theme to Fluent Theme Builder ([#133](https://github.com/bdlukaa/fluent_ui/issues/133))
- Add more customization options to PaneItem ([#111](https://github.com/bdlukaa/fluent_ui/issues/111), [#144](https://github.com/bdlukaa/fluent_ui/issues/144))
- Properly add item key to `PaneItem` in top mode ([#143](https://github.com/bdlukaa/fluent_ui/issues/143))
- Added the helper functions `NavigationIndicator.end` and `NavigationIndicator.sticky`
- **BREAKING** Removed `NavigationPane.defaultNavigationIndicator`
- **BREAKING** Replaced `offsets` and `sizes` with `pane` in `NavigationPane`

Before:
```dart
pane: NavigationPane(
indicatorBuilder: ({
required BuildContext context,
/// The navigation pane corresponding to this indicator
required NavigationPane pane,
/// Corresponds to the current display mode. If top, Axis.vertical
/// is passed, otherwise Axis.vertical
Axis? axis,
/// Corresponds to the pane itself as a widget. The indicator is
/// rendered over the whole pane.
required Widget child,
}) {
if (pane.selected == null) return child;
assert(debugCheckHasFluentTheme(context));
final theme = NavigationPaneThemeData.of(context);
axis??= Axis.horizontal;
return EndNavigationIndicator(
index: pane.selected,
offsets: () => pane.effectiveItems.getPaneItemsOffsets (pane.paneKey),
sizes: pane.effectiveItems.getPaneItemsSizes,
child: child,
color: theme.highlightColor,
curve: theme.animationCurve ?? Curves.linear,
axis: axis,
);
},
),
```

Now:
```dart
pane: NavigationPane(
indicatorBuilder: ({
required BuildContext context,
/// The navigation pane corresponding to this indicator
required NavigationPane pane,
/// Corresponds to the current display mode. If top, Axis.vertical
/// is passed, otherwise Axis.vertical
required Axis axis,
/// Corresponds to the pane itself as a widget. The indicator is
/// rendered over the whole pane.
required Widget child,
}) {
if (pane.selected == null) return child;
assert(debugCheckHasFluentTheme(context));
final theme = NavigationPaneThemeData.of(context);
return EndNavigationIndicator(
index: pane.selected,
pane: pane,
child: child,
color: theme.highlightColor,
curve: theme.animationCurve ?? Curves.linear,
axis: axis,
);
},
),
```

## [3.7.0] - Breaking changes - [21/01/2022]

Expand Down
45 changes: 5 additions & 40 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -165,48 +165,15 @@ class _MyHomePageState extends State<MyHomePage> {
),
),
displayMode: appTheme.displayMode,
indicatorBuilder: ({
required BuildContext context,
required NavigationPane pane,
Axis? axis,
required Widget child,
}) {
if (pane.selected == null) return child;
axis ??= Axis.horizontal;
assert(debugCheckHasFluentTheme(context));
final theme = NavigationPaneTheme.of(context);
indicatorBuilder: () {
switch (appTheme.indicator) {
case NavigationIndicators.end:
return EndNavigationIndicator(
index: pane.selected!,
offsets: () =>
pane.effectiveItems.getPaneItemsOffsets(pane.paneKey),
sizes: pane.effectiveItems.getPaneItemsSizes,
child: child,
color: theme.highlightColor,
curve: theme.animationCurve ?? Curves.linear,
axis: axis,
);
return NavigationIndicator.end;
case NavigationIndicators.sticky:
return NavigationPane.defaultNavigationIndicator(
context: context,
axis: axis,
pane: pane,
child: child,
);
default:
return NavigationIndicator(
index: pane.selected!,
offsets: () =>
pane.effectiveItems.getPaneItemsOffsets(pane.paneKey),
sizes: pane.effectiveItems.getPaneItemsSizes,
child: child,
color: theme.highlightColor,
curve: theme.animationCurve ?? Curves.linear,
axis: axis,
);
return NavigationIndicator.sticky;
}
},
}(),
items: [
// It doesn't look good when resizing from compact to open
// PaneItemHeader(header: Text('User Interaction')),
Expand All @@ -221,9 +188,7 @@ class _MyHomePageState extends State<MyHomePage> {
PaneItemSeparator(),
PaneItem(
icon: const Icon(FluentIcons.color),
title: const Text(
'Colors',
),
title: const Text('Colors'),
),
PaneItem(
icon: const Icon(FluentIcons.icon_sets_flag),
Expand Down
100 changes: 67 additions & 33 deletions lib/src/controls/navigation/navigation_view/indicators.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ part of 'view.dart';
typedef NavigationIndicatorBuilder = Widget Function({
required BuildContext context,
required NavigationPane pane,
Axis? axis,
required Axis axis,
required Widget child,
});

Expand All @@ -19,27 +19,68 @@ class NavigationIndicator extends StatefulWidget {
/// to render the selected indicator.
const NavigationIndicator({
Key? key,
required this.offsets,
required this.sizes,
required this.index,
required this.child,
required this.pane,
required this.axis,
this.curve = Curves.linear,
this.color,
}) : super(key: key);

/// Creates a [StickyNavigationIndicator]
static Widget sticky({
required BuildContext context,
required NavigationPane pane,
required Axis axis,
required Widget child,
}) {
if (pane.selected == null) return child;
assert(debugCheckHasFluentTheme(context));
final theme = NavigationPaneTheme.of(context);

final left = theme.iconPadding?.left ?? theme.labelPadding?.left ?? 0;
final right = theme.labelPadding?.right ?? theme.iconPadding?.right ?? 0;

return StickyNavigationIndicator(
index: pane.selected!,
pane: pane,
child: child,
color: theme.highlightColor,
curve: theme.animationCurve ?? Curves.linear,
axis: axis,
topPadding: EdgeInsets.only(left: left, right: right),
);
}

/// Creates an [EndNavigationIndicator]
static Widget end({
required BuildContext context,
required NavigationPane pane,
required Axis axis,
required Widget child,
}) {
if (pane.selected == null) return child;
assert(debugCheckHasFluentTheme(context));
final theme = NavigationPaneTheme.of(context);

return EndNavigationIndicator(
index: pane.selected!,
pane: pane,
child: child,
color: theme.highlightColor,
curve: theme.animationCurve ?? Curves.linear,
axis: axis,
);
}

/// The [NavigationPane]. It can be open, compact, closed or top.
final Widget child;

/// The current selected index;
final int index;

/// A function that tells the indicator the item offsets.
final List<Offset> Function() offsets;

/// A function that tells the indicator the item sizes. The sizes
/// must not be [Size.infinite]
final List<Size> Function() sizes;
/// The navigation pane
final NavigationPane pane;

/// The axis corresponding to the current navigation pane. If it's
/// a top pane, [Axis.vertical] will be provided, otherwise
Expand Down Expand Up @@ -81,9 +122,11 @@ class NavigationIndicatorState<T extends NavigationIndicator> extends State<T> {

void fetch() {
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
final _offsets = widget.offsets();
final _sizes = widget.sizes();
if (mounted && offsets != _offsets && _sizes != sizes) {
final _offsets = widget.pane.effectiveItems.getPaneItemsOffsets(
widget.pane.paneKey,
);
final _sizes = widget.pane.effectiveItems.getPaneItemsSizes();
if (mounted && (offsets != _offsets || _sizes != sizes)) {
offsets = _offsets;
sizes = _sizes;
}
Expand All @@ -100,8 +143,7 @@ class NavigationIndicatorState<T extends NavigationIndicator> extends State<T> {
class EndNavigationIndicator extends NavigationIndicator {
const EndNavigationIndicator({
Key? key,
required List<Offset> Function() offsets,
required List<Size> Function() sizes,
required NavigationPane pane,
required int index,
required Widget child,
required Axis axis,
Expand All @@ -110,10 +152,9 @@ class EndNavigationIndicator extends NavigationIndicator {
}) : super(
key: key,
axis: axis,
pane: pane,
child: child,
index: index,
offsets: offsets,
sizes: sizes,
curve: curve,
color: color,
);
Expand All @@ -132,7 +173,7 @@ class _EndNavigationIndicatorState
widget.child,
...List.generate(offsets!.length, (index) {
if (widget.index != index) return const SizedBox.shrink();
final isTop = widget.axis != Axis.horizontal;
final isTop = widget.axis == Axis.vertical;
final offset = offsets![index];

final size = sizes![index];
Expand All @@ -144,12 +185,12 @@ class _EndNavigationIndicatorState
horizontal: isTop ? 10.0 : 0.0,
),
width: isTop ? size.width : 6.0,
height: isTop ? 4 : size.height,
height: isTop ? 6.0 : size.height,
color: widget.color,
),
);

// debugPrint('at $offset with $size');
debugPrint('at $offset with $size');

if (isTop) {
return Positioned(
Expand Down Expand Up @@ -185,8 +226,7 @@ class StickyNavigationIndicator extends NavigationIndicator {
/// Creates a sticky navigation indicator.
const StickyNavigationIndicator({
Key? key,
required List<Offset> Function() offsets,
required List<Size> Function() sizes,
required NavigationPane pane,
required int index,
required Widget child,
required Axis axis,
Expand All @@ -196,10 +236,9 @@ class StickyNavigationIndicator extends NavigationIndicator {
}) : super(
key: key,
axis: axis,
pane: pane,
child: child,
index: index,
offsets: offsets,
sizes: sizes,
curve: curve,
color: color,
);
Expand Down Expand Up @@ -428,7 +467,11 @@ class _StickyPainter extends CustomPainter {
bool shouldRebuildSemantics(_StickyPainter oldDelegate) => false;
}

extension OffsetExtension on Offset {
extension _OffsetExtension on Offset {
/// Gets the value based on [axis]
///
/// If [Axis.horizontal], [dy] is going to be returned. Otherwise, [dx] is
/// returned.
double fromAxis(Axis axis) {
if (axis == Axis.horizontal) {
return dy;
Expand All @@ -437,12 +480,3 @@ extension OffsetExtension on Offset {
}
}
}

// extension _size on Size {
// double fromAxis(Axis axis) {
// if (axis == Axis.horizontal)
// return height;
// else
// return width;
// }
// }
Loading

0 comments on commit a5a03a8

Please sign in to comment.