render method
Renders the widget onto the provided buffer within the specified area.
Implementation
@override
void render(Buffer buffer, Rect area) {
if (area.width <= 0 || area.height <= 0) return;
final clamped = fraction.clamp(0.0, 1.0);
final eased = easing(clamped);
final progressVal = (eased * area.width).clamp(0.0, area.width.toDouble());
final filledWidth = progressVal.floor();
// Determine the percentage text if shown
String? pctText;
int? pctStartIdx;
if (showPercentage) {
pctText = '${(eased * 100).toInt().clamp(0, 100)}%';
if (pctText.length < area.width - 2) {
pctStartIdx = ((area.width - pctText.length) / 2).floor();
} else {
pctText = null;
}
}
final hasGradient = startColor != null && endColor != null;
var cellStyle = style;
for (var x = 0; x < area.width; x++) {
// 1. Calculate style (interpolate color if gradient enabled)
if (hasGradient) {
final t = area.width > 1 ? x / (area.width - 1) : 0.0;
final r = (startColor!.r + t * (endColor!.r - startColor!.r)).round();
final g = (startColor!.g + t * (endColor!.g - startColor!.g)).round();
final b = (startColor!.b + t * (endColor!.b - startColor!.b)).round();
cellStyle = Style(
foreground: Color(r, g, b),
background: style.background,
modifiers: style.modifiers,
);
}
// 2. Determine character
String char = '░'; // background character
// Check if we are inside the percentage text range
if (pctText != null &&
pctStartIdx != null &&
x >= pctStartIdx &&
x < pctStartIdx + pctText.length) {
char = pctText[x - pctStartIdx];
} else {
if (x < filledWidth) {
char = '█';
} else if (x == filledWidth) {
final remainder = progressVal - filledWidth;
if (smooth) {
final idx = (remainder * 8).round() - 1;
if (idx >= 0 && idx < 8) {
char = eighths[idx];
} else if (idx >= 8) {
char = '█';
}
} else {
if (remainder >= 0.5) {
char = '█';
}
}
}
}
final cell = buffer.getCell(x, 0);
if (cell != null) {
cell.char = char;
cell.style = cellStyle;
}
}
}