diff --git a/CHANGELOG.md b/CHANGELOG.md index ca8a311..27ddfcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,26 +1,29 @@ -## 2.0.0 +# 2.0.1 + +* Wrapped canvas with a transparent `Material` to be able to use it outside `Scaffold`. -Desktop and web experience is significantly improved with this update. Check [new features](#new-features-and-enhancements) and [updated readme](https://pub.dev/packages/pie_menu) for details. +## 2.0.0 -* Added live Flutter web demo, [check it out!](https://rasitayaz.github.io/flutter-pie-menu) +* Desktop and web experience is significantly improved with this update. Check [new features](#new-features-and-enhancements) and [updated readme](https://pub.dev/packages/pie_menu) for details. +* Added live Flutter web demo, [give it a try!](https://rasitayaz.github.io/flutter-pie-menu) ### Breaking changes -#### Inside `PieTheme` +**Inside `PieTheme`;** * Changed `tooltip` type from `String` to `Widget`, you can now use custom widgets as tooltips. * Renamed `tooltipStyle` to `tooltipTextStyle`. * Renamed `distance` to `radius`. * `bouncingMenu` is renamed to `childBounceEnabled`, and all the related attributes that starts with `menuBounce...` are renamed to `childBounce...` to avoid confusion. -#### Other +**Other;** * `onTap` callback inside `PieMenu` is renamed to `onPressed`. Also added a new `onPressedWithDevice` callback that provides `PointerDeviceKind`, allowing you to distinguish between mouse and touch events. * Removed `padding` from `PieAction` since it already has a `child` that can be wrapped with a `Padding` widget. ### New features and enhancements -#### Inside `PieTheme` +**Inside `PieTheme`;** * Added `rightClickShowsMenu` and `leftClickShowsMenu` attributes to customize the mouse behavior. [#13](https://github.com/rasitayaz/flutter-pie-menu/issues/13) * Added `customAngle` and `customAngleAnchor` attributes to set a fixed positioning for the buttons. [#34](https://github.com/rasitayaz/flutter-pie-menu/issues/34) @@ -28,7 +31,7 @@ Desktop and web experience is significantly improved with this update. Check [ne * Added `tooltipUseFittedBox` to allow the tooltip to be resized to fit the text into a single line. * Added `pointerDecoration`, allowing you to style the widget at the center of the menu. -#### Other +**Other;** * Hovering over the buttons with mouse highlights them now. Also, cursor changes when the menu or buttons are hovered. [#16](https://github.com/rasitayaz/flutter-pie-menu/issues/16) * Improved dynamic menu angle calculation (again). diff --git a/lib/src/pie_canvas_overlay.dart b/lib/src/pie_canvas_overlay.dart index c5e1d2e..812ba1d 100644 --- a/lib/src/pie_canvas_overlay.dart +++ b/lib/src/pie_canvas_overlay.dart @@ -195,197 +195,200 @@ class PieCanvasOverlayState extends State final menuRenderBox = _menuRenderBox; final menuChild = _menuChild; - return MouseRegion( - cursor: _hoveredAction != null - ? SystemMouseCursors.click - : SystemMouseCursors.basic, - child: Stack( - children: [ - Listener( - behavior: HitTestBehavior.translucent, - onPointerDown: (event) => _pointerDown(event.position), - onPointerMove: (event) => _pointerMove(event.position), - onPointerHover: - menuActive ? (event) => _pointerMove(event.position) : null, - onPointerUp: (event) => _pointerUp(event.position), - child: ScrollConfiguration( - behavior: ScrollConfiguration.of(context).copyWith( - physics: - menuActive ? const NeverScrollableScrollPhysics() : null, - ), - child: IgnorePointer( - ignoring: menuActive, - child: widget.child, + return Material( + type: MaterialType.transparency, + child: MouseRegion( + cursor: _hoveredAction != null + ? SystemMouseCursors.click + : SystemMouseCursors.basic, + child: Stack( + children: [ + Listener( + behavior: HitTestBehavior.translucent, + onPointerDown: (event) => _pointerDown(event.position), + onPointerMove: (event) => _pointerMove(event.position), + onPointerHover: + menuActive ? (event) => _pointerMove(event.position) : null, + onPointerUp: (event) => _pointerUp(event.position), + child: ScrollConfiguration( + behavior: ScrollConfiguration.of(context).copyWith( + physics: + menuActive ? const NeverScrollableScrollPhysics() : null, + ), + child: IgnorePointer( + ignoring: menuActive, + child: widget.child, + ), ), ), - ), - IgnorePointer( - child: AnimatedOpacity( - duration: _forceClose ? Duration.zero : _theme.fadeDuration, - opacity: menuActive ? 1 : 0, - curve: Curves.ease, - child: Stack( - children: [ - /// Overlay - Positioned.fill( - child: ColoredBox( - color: _theme.overlayColor ?? - (_theme.brightness == Brightness.light - ? Colors.white.withOpacity(0.8) - : Colors.black.withOpacity(0.8)), + IgnorePointer( + child: AnimatedOpacity( + duration: _forceClose ? Duration.zero : _theme.fadeDuration, + opacity: menuActive ? 1 : 0, + curve: Curves.ease, + child: Stack( + children: [ + /// Overlay + Positioned.fill( + child: ColoredBox( + color: _theme.overlayColor ?? + (_theme.brightness == Brightness.light + ? Colors.white.withOpacity(0.8) + : Colors.black.withOpacity(0.8)), + ), ), - ), - - /// Pie Menu child - if (menuRenderBox != null && - menuRenderBox.attached && - menuChild != null) - () { - final menuOffset = - menuRenderBox.localToGlobal(Offset.zero); - - return Positioned( - top: menuOffset.dy - _canvasOffset.dy, - left: menuOffset.dx - _canvasOffset.dx, - child: AnimatedOpacity( - opacity: _hoveredAction != null ? 0.5 : 1, - duration: _theme.hoverDuration, - curve: Curves.ease, - child: SizedBox.fromSize( - size: menuRenderBox.size, - child: menuChild, - ), - ), - ); - }.call(), - - /// Tooltip - if (tooltip != null) - () { - final tooltipAlignment = _theme.tooltipCanvasAlignment; - - Widget child = AnimatedOpacity( - opacity: menuActive && _hoveredAction != null ? 1 : 0, - duration: _theme.hoverDuration, - curve: Curves.ease, - child: Padding( - padding: _theme.tooltipPadding, - child: DefaultTextStyle.merge( - textAlign: _theme.tooltipTextAlign ?? - (px < cw / 2 - ? TextAlign.right - : TextAlign.left), - style: TextStyle( - fontSize: 32, - fontWeight: FontWeight.bold, - color: _theme.brightness == Brightness.light - ? Colors.black - : Colors.white, - ) - .merge(widget.theme.tooltipTextStyle) - .merge(_theme.tooltipTextStyle), - child: tooltip, - ), - ), - ); - if (_theme.tooltipUseFittedBox) { - child = FittedBox(child: child); - } + /// Pie Menu child + if (menuRenderBox != null && + menuRenderBox.attached && + menuChild != null) + () { + final menuOffset = + menuRenderBox.localToGlobal(Offset.zero); - if (tooltipAlignment != null) { - return Align( - alignment: tooltipAlignment, - child: child, + return Positioned( + top: menuOffset.dy - _canvasOffset.dy, + left: menuOffset.dx - _canvasOffset.dx, + child: AnimatedOpacity( + opacity: _hoveredAction != null ? 0.5 : 1, + duration: _theme.hoverDuration, + curve: Curves.ease, + child: SizedBox.fromSize( + size: menuRenderBox.size, + child: menuChild, + ), + ), ); - } else { - final offsets = [ - _pointerOffset, - for (var i = 0; i < _actions.length; i++) - _getActionOffset(i), - ]; - - double? getTopDistance() { - if (py >= ch / 2) return null; - - final dyMax = offsets - .map((o) => o.dy) - .reduce((dy1, dy2) => max(dy1, dy2)); - - return dyMax - - _canvasOffset.dy + - _theme.buttonSize / 2; - } + }.call(), - double? getBottomDistance() { - if (py < ch / 2) return null; + /// Tooltip + if (tooltip != null) + () { + final tooltipAlignment = _theme.tooltipCanvasAlignment; - final dyMin = offsets - .map((o) => o.dy) - .reduce((dy1, dy2) => min(dy1, dy2)); + Widget child = AnimatedOpacity( + opacity: menuActive && _hoveredAction != null ? 1 : 0, + duration: _theme.hoverDuration, + curve: Curves.ease, + child: Padding( + padding: _theme.tooltipPadding, + child: DefaultTextStyle.merge( + textAlign: _theme.tooltipTextAlign ?? + (px < cw / 2 + ? TextAlign.right + : TextAlign.left), + style: TextStyle( + fontSize: 32, + fontWeight: FontWeight.bold, + color: _theme.brightness == Brightness.light + ? Colors.black + : Colors.white, + ) + .merge(widget.theme.tooltipTextStyle) + .merge(_theme.tooltipTextStyle), + child: tooltip, + ), + ), + ); - return ch - - dyMin + - _canvasOffset.dy + - _theme.buttonSize / 2; + if (_theme.tooltipUseFittedBox) { + child = FittedBox(child: child); } - return Positioned( - top: getTopDistance(), - bottom: getBottomDistance(), - left: 0, - right: 0, - child: Align( - alignment: px < cw / 2 - ? Alignment.centerRight - : Alignment.centerLeft, + if (tooltipAlignment != null) { + return Align( + alignment: tooltipAlignment, child: child, - ), - ); - } - }.call(), - - /// Action buttons - Flow( - delegate: PieDelegate( - bounceAnimation: _bounceAnimation, - pointerOffset: _pointerOffset, - canvasOffset: _canvasOffset, - baseAngle: _baseAngle, - angleDiff: _angleDiff, - theme: _theme, - ), - children: [ - DecoratedBox( - decoration: _theme.pointerDecoration ?? - BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: _theme.pointerColor ?? - (_theme.brightness == Brightness.light - ? Colors.black.withOpacity(0.35) - : Colors.white.withOpacity(0.5)), - width: 4, - ), + ); + } else { + final offsets = [ + _pointerOffset, + for (var i = 0; i < _actions.length; i++) + _getActionOffset(i), + ]; + + double? getTopDistance() { + if (py >= ch / 2) return null; + + final dyMax = offsets + .map((o) => o.dy) + .reduce((dy1, dy2) => max(dy1, dy2)); + + return dyMax - + _canvasOffset.dy + + _theme.buttonSize / 2; + } + + double? getBottomDistance() { + if (py < ch / 2) return null; + + final dyMin = offsets + .map((o) => o.dy) + .reduce((dy1, dy2) => min(dy1, dy2)); + + return ch - + dyMin + + _canvasOffset.dy + + _theme.buttonSize / 2; + } + + return Positioned( + top: getTopDistance(), + bottom: getBottomDistance(), + left: 0, + right: 0, + child: Align( + alignment: px < cw / 2 + ? Alignment.centerRight + : Alignment.centerLeft, + child: child, ), + ); + } + }.call(), + + /// Action buttons + Flow( + delegate: PieDelegate( + bounceAnimation: _bounceAnimation, + pointerOffset: _pointerOffset, + canvasOffset: _canvasOffset, + baseAngle: _baseAngle, + angleDiff: _angleDiff, + theme: _theme, ), - for (int i = 0; i < _actions.length; i++) - PieButton( - action: _actions[i], - angle: _getActionAngle(i), - menuActive: menuActive, - hovered: i == _hoveredAction, - theme: _theme, - fadeDuration: _theme.fadeDuration, - hoverDuration: _theme.hoverDuration, + children: [ + DecoratedBox( + decoration: _theme.pointerDecoration ?? + BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: _theme.pointerColor ?? + (_theme.brightness == Brightness.light + ? Colors.black.withOpacity(0.35) + : Colors.white.withOpacity(0.5)), + width: 4, + ), + ), ), - ], - ), - ], + for (int i = 0; i < _actions.length; i++) + PieButton( + action: _actions[i], + angle: _getActionAngle(i), + menuActive: menuActive, + hovered: i == _hoveredAction, + theme: _theme, + fadeDuration: _theme.fadeDuration, + hoverDuration: _theme.hoverDuration, + ), + ], + ), + ], + ), ), ), - ), - ], + ], + ), ), ); } diff --git a/pubspec.yaml b/pubspec.yaml index 4299684..b1e689c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: pie_menu description: A Flutter package that provides a highly customizable circular/radial context menu -version: 2.0.0 +version: 2.0.1 homepage: https://github.com/rasitayaz/flutter-pie-menu repository: https://github.com/rasitayaz/flutter-pie-menu issue_tracker: https://github.com/rasitayaz/flutter-pie-menu/issues