mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-08-03 01:00:14 +08:00
178 lines
4.5 KiB
Dart
178 lines
4.5 KiB
Dart
import 'dart:math' as math;
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
class VoteDecoration extends Decoration {
|
|
const VoteDecoration({
|
|
required this.color,
|
|
required this.percentage,
|
|
required this.border,
|
|
required this.borderRadius,
|
|
});
|
|
|
|
final Color color;
|
|
final double percentage;
|
|
final BoxBorder border;
|
|
final BorderRadius borderRadius;
|
|
|
|
@override
|
|
EdgeInsetsGeometry get padding => border.dimensions;
|
|
|
|
@override
|
|
Path getClipPath(Rect rect, TextDirection textDirection) {
|
|
return Path()..addRRect(borderRadius.resolve(textDirection).toRRect(rect));
|
|
}
|
|
|
|
@override
|
|
bool operator ==(Object other) {
|
|
if (identical(this, other)) {
|
|
return true;
|
|
}
|
|
if (other.runtimeType != runtimeType) {
|
|
return false;
|
|
}
|
|
return other is VoteDecoration &&
|
|
other.color == color &&
|
|
other.border == border &&
|
|
other.borderRadius == borderRadius &&
|
|
other.percentage == percentage;
|
|
}
|
|
|
|
@override
|
|
int get hashCode => Object.hash(color, border, borderRadius, percentage);
|
|
|
|
@override
|
|
bool hitTest(Size size, Offset position, {TextDirection? textDirection}) {
|
|
assert((Offset.zero & size).contains(position));
|
|
final Offset center = size.center(Offset.zero);
|
|
final double distance = (position - center).distance;
|
|
return distance <= math.min(size.width, size.height) / 2.0;
|
|
}
|
|
|
|
@override
|
|
BoxPainter createBoxPainter([VoidCallback? onChanged]) {
|
|
assert(onChanged != null);
|
|
return _VoteDecorationPainter(this, onChanged);
|
|
}
|
|
}
|
|
|
|
class _VoteDecorationPainter extends BoxPainter {
|
|
_VoteDecorationPainter(this._decoration, super.onChanged);
|
|
|
|
final VoteDecoration _decoration;
|
|
|
|
Paint? _cachedBackgroundPaint;
|
|
Rect? _rectForCachedBackgroundPaint;
|
|
Paint _getBackgroundPaint(Rect rect, TextDirection? textDirection) {
|
|
assert(
|
|
_rectForCachedBackgroundPaint == null,
|
|
);
|
|
|
|
if (_cachedBackgroundPaint == null) {
|
|
final paint = Paint()..color = _decoration.color;
|
|
_cachedBackgroundPaint = paint;
|
|
}
|
|
|
|
return _cachedBackgroundPaint!;
|
|
}
|
|
|
|
void _paintBox(
|
|
Canvas canvas,
|
|
Rect rect,
|
|
Paint paint,
|
|
TextDirection? textDirection,
|
|
) {
|
|
if (_decoration.percentage == 1.0) {
|
|
canvas.drawRRect(
|
|
_decoration.borderRadius.resolve(textDirection).toRRect(rect),
|
|
paint,
|
|
);
|
|
} else {
|
|
final borderRadius = BorderRadius.horizontal(
|
|
left: _decoration.borderRadius.topLeft,
|
|
);
|
|
canvas.drawRRect(
|
|
borderRadius.resolve(textDirection).toRRect(rect),
|
|
paint,
|
|
);
|
|
}
|
|
}
|
|
|
|
void _paintBackgroundColor(
|
|
Canvas canvas,
|
|
Rect rect,
|
|
TextDirection? textDirection,
|
|
) {
|
|
final Rect adjustedRect = _adjustedRectOnOutlinedBorder(
|
|
rect,
|
|
textDirection,
|
|
);
|
|
_paintBox(
|
|
canvas,
|
|
adjustedRect,
|
|
_getBackgroundPaint(rect, textDirection),
|
|
textDirection,
|
|
);
|
|
}
|
|
|
|
double _calculateAdjustedSide(BorderSide side) {
|
|
if (side.color.alpha == 255 && side.style == .solid) {
|
|
return side.strokeInset;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Rect _adjustedRectOnOutlinedBorder(Rect rect, TextDirection? textDirection) {
|
|
final border = _decoration.border as Border;
|
|
|
|
final EdgeInsets insets =
|
|
EdgeInsets.fromLTRB(
|
|
_calculateAdjustedSide(border.left),
|
|
_calculateAdjustedSide(border.top),
|
|
_calculateAdjustedSide(border.right),
|
|
_calculateAdjustedSide(border.bottom),
|
|
) /
|
|
2;
|
|
|
|
return Rect.fromLTRB(
|
|
rect.left + insets.left,
|
|
rect.top + insets.top,
|
|
rect.right - insets.right,
|
|
rect.bottom - insets.bottom,
|
|
);
|
|
}
|
|
|
|
@override
|
|
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
|
|
assert(configuration.size != null);
|
|
final Rect rect = offset & configuration.size!;
|
|
final TextDirection? textDirection = configuration.textDirection;
|
|
if (_decoration.percentage > 0) {
|
|
final Rect bgRect;
|
|
if (_decoration.percentage == 1.0) {
|
|
bgRect = rect;
|
|
} else {
|
|
bgRect =
|
|
offset &
|
|
Size(
|
|
configuration.size!.width * (_decoration.percentage),
|
|
configuration.size!.height,
|
|
);
|
|
}
|
|
_paintBackgroundColor(canvas, bgRect, textDirection);
|
|
}
|
|
_decoration.border.paint(
|
|
canvas,
|
|
rect,
|
|
shape: .rectangle,
|
|
borderRadius: _decoration.borderRadius.resolve(textDirection),
|
|
textDirection: configuration.textDirection,
|
|
);
|
|
}
|
|
|
|
@override
|
|
String toString() {
|
|
return 'VotePainter for $_decoration';
|
|
}
|
|
}
|