mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-09 22:57:21 +00:00
102 lines
2.9 KiB
Dart
102 lines
2.9 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:syncrow_web/utils/color_manager.dart';
|
|
|
|
class OccupancyPaintItem {
|
|
final int index;
|
|
final int value;
|
|
final DateTime date;
|
|
|
|
const OccupancyPaintItem({
|
|
required this.index,
|
|
required this.value,
|
|
required this.date,
|
|
});
|
|
}
|
|
|
|
class OccupancyPainter extends CustomPainter {
|
|
OccupancyPainter({
|
|
required this.items,
|
|
required this.maxValue,
|
|
this.hoveredItem,
|
|
});
|
|
|
|
final List<OccupancyPaintItem> items;
|
|
final int maxValue;
|
|
final OccupancyPaintItem? hoveredItem;
|
|
|
|
static const double cellSize = 16.0;
|
|
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
final fillPaint = Paint();
|
|
final borderPaint = Paint()
|
|
..color = ColorsManager.grayBorder.withValues(alpha: 0.4)
|
|
..style = PaintingStyle.stroke;
|
|
final hoveredBorderPaint = Paint()
|
|
..color = Colors.black
|
|
..style = PaintingStyle.stroke
|
|
..strokeWidth = 1.5;
|
|
|
|
for (final item in items) {
|
|
final column = item.index ~/ 7;
|
|
final row = item.index % 7;
|
|
|
|
final x = column * cellSize;
|
|
final y = row * cellSize;
|
|
|
|
fillPaint.color = _getColor(item.value);
|
|
final rect = Rect.fromLTWH(x, y, cellSize, cellSize);
|
|
canvas.drawRect(rect, fillPaint);
|
|
|
|
// Highlight the hovered item
|
|
if (hoveredItem != null && hoveredItem!.index == item.index) {
|
|
canvas.drawRect(rect, hoveredBorderPaint);
|
|
} else {
|
|
_drawDashedLine(
|
|
canvas,
|
|
Offset(x, y),
|
|
Offset(x + cellSize, y),
|
|
borderPaint,
|
|
);
|
|
_drawDashedLine(
|
|
canvas,
|
|
Offset(x, y + cellSize),
|
|
Offset(x + cellSize, y + cellSize),
|
|
borderPaint,
|
|
);
|
|
|
|
canvas.drawLine(Offset(x, y), Offset(x, y + cellSize), borderPaint);
|
|
canvas.drawLine(Offset(x + cellSize, y),
|
|
Offset(x + cellSize, y + cellSize), borderPaint);
|
|
}
|
|
}
|
|
}
|
|
|
|
void _drawDashedLine(Canvas canvas, Offset start, Offset end, Paint paint) {
|
|
const dashWidth = 2.0;
|
|
const dashSpace = 4.0;
|
|
final totalLength = (end - start).distance;
|
|
final direction = (end - start) / (end - start).distance;
|
|
|
|
var currentLength = 0.0;
|
|
while (currentLength < totalLength) {
|
|
final dashStart = start + direction * currentLength;
|
|
final nextLength = currentLength + dashWidth;
|
|
final dashEnd = start +
|
|
direction * (nextLength < totalLength ? nextLength : totalLength);
|
|
canvas.drawLine(dashStart, dashEnd, paint);
|
|
currentLength = nextLength + dashSpace;
|
|
}
|
|
}
|
|
|
|
Color _getColor(int value) {
|
|
if (maxValue == 0) return ColorsManager.vividBlue.withValues(alpha: 0);
|
|
final opacity = value.clamp(0, maxValue) / maxValue;
|
|
return ColorsManager.vividBlue.withValues(alpha: opacity);
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(covariant OccupancyPainter oldDelegate) =>
|
|
oldDelegate.hoveredItem != hoveredItem;
|
|
}
|