import 'dart:math'; import 'package:shadcn_flutter/shadcn_flutter.dart'; class ShadcnWindowButton extends StatelessWidget { final Widget icon; final VoidCallback onPressed; final Color? hoverBackgroundColor; const ShadcnWindowButton({ super.key, required this.icon, required this.onPressed, this.hoverBackgroundColor, }); @override Widget build(BuildContext context) { return SizedBox( width: 45, height: 32, child: IconButton( variance: ButtonVariance.ghost.copyWith( decoration: (context, states, value) { final decoration = ButtonVariance.ghost.decoration(context, states) as BoxDecoration; if (hoverBackgroundColor != null && states.contains(WidgetState.hovered)) { return decoration.copyWith( borderRadius: BorderRadius.zero, color: hoverBackgroundColor, ); } return decoration.copyWith( borderRadius: BorderRadius.zero, ); }, ), icon: icon, onPressed: onPressed, ), ); } } /// Close class CloseIcon extends StatelessWidget { final Color color; const CloseIcon({super.key, required this.color}); @override Widget build(BuildContext context) => Align( alignment: Alignment.topLeft, child: Stack(children: [ // Use rotated containers instead of a painter because it renders slightly crisper than a painter for some reason. Transform.rotate( angle: pi * .25, child: Center(child: Container(width: 14, height: 1, color: color))), Transform.rotate( angle: pi * -.25, child: Center(child: Container(width: 14, height: 1, color: color))), ]), ); } /// Maximize class MaximizeIcon extends StatelessWidget { final Color color; const MaximizeIcon({super.key, required this.color}); @override Widget build(BuildContext context) => _AlignedPaint(_MaximizePainter(color)); } class _MaximizePainter extends _IconPainter { _MaximizePainter(super.color); @override void paint(Canvas canvas, Size size) { Paint p = getPaint(color); canvas.drawRect(Rect.fromLTRB(0, 0, size.width - 1, size.height - 1), p); } } /// Restore class RestoreIcon extends StatelessWidget { final Color color; const RestoreIcon({ super.key, required this.color, }); @override Widget build(BuildContext context) => _AlignedPaint(_RestorePainter(color)); } class _RestorePainter extends _IconPainter { _RestorePainter(super.color); @override void paint(Canvas canvas, Size size) { Paint p = getPaint(color); canvas.drawRect(Rect.fromLTRB(0, 2, size.width - 2, size.height), p); canvas.drawLine(const Offset(2, 2), const Offset(2, 0), p); canvas.drawLine(const Offset(2, 0), Offset(size.width, 0), p); canvas.drawLine( Offset(size.width, 0), Offset(size.width, size.height - 2), p); canvas.drawLine(Offset(size.width, size.height - 2), Offset(size.width - 2, size.height - 2), p); } } /// Minimize class MinimizeIcon extends StatelessWidget { final Color color; const MinimizeIcon({super.key, required this.color}); @override Widget build(BuildContext context) => _AlignedPaint(_MinimizePainter(color)); } class _MinimizePainter extends _IconPainter { _MinimizePainter(super.color); @override void paint(Canvas canvas, Size size) { Paint p = getPaint(color); canvas.drawLine( Offset(0, size.height / 2), Offset(size.width, size.height / 2), p); } } /// Helpers abstract class _IconPainter extends CustomPainter { _IconPainter(this.color); final Color color; @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; } class _AlignedPaint extends StatelessWidget { const _AlignedPaint(this.painter); final CustomPainter painter; @override Widget build(BuildContext context) { return Align( alignment: Alignment.center, child: CustomPaint(size: const Size(10, 10), painter: painter), ); } } Paint getPaint(Color color, [bool isAntiAlias = false]) => Paint() ..color = color ..style = PaintingStyle.stroke ..isAntiAlias = isAntiAlias ..strokeWidth = 1;