spotube/lib/components/titlebar/titlebar_icon_buttons.dart
2025-03-28 22:24:23 +06:00

156 lines
4.3 KiB
Dart

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;