paint method
Default paint implementation.
RenderBox paints no self-content; it forwards painting to its RenderBox children. Subclasses override to draw their own content.
Implementation
@override
void paint(PaintingContext context, Offset offset) {
final originX = offset.dx + x;
final originY = offset.dy + y;
final canvas = context.canvas;
final visualLayout = _ensureVisualLayout(width);
final cursor = visualLayout.positionForOffset(
_cursorSourceOffset(),
affinity: _cursorAffinity,
);
var effectiveScrollLine = _scrollLine.clamp(
0,
(visualLayout.lines.length - height).clamp(0, visualLayout.lines.length),
);
if (_focused && (_softWrap || _maxHeightLines != null) && height > 0) {
if (cursor.row < effectiveScrollLine) {
effectiveScrollLine = cursor.row;
} else if (cursor.row >= effectiveScrollLine + height) {
effectiveScrollLine = cursor.row - height + 1;
}
}
var effectiveScrollCell = _softWrap ? 0 : _scrollCell;
if (_focused && _maxHeightLines != null && !_softWrap && width > 0) {
if (cursor.cell < effectiveScrollCell) {
effectiveScrollCell = cursor.cell;
} else if (cursor.cell >= effectiveScrollCell + width) {
effectiveScrollCell = cursor.cell - width + 1;
}
}
if (_backgroundColor != null) {
canvas.fillRect(
Rect.fromLTWH(originX, originY, width, height),
_backgroundColor!,
);
}
final isEmpty = _lines.length == 1 && _lines[0].isEmpty;
if (isEmpty && _placeholder != null && !_focused) {
// Render placeholder dimmed on first row only, cell-aware.
final dim = Color(
_color.r * 0.5,
_color.g * 0.5,
_color.b * 0.5,
_color.a,
);
final ph = _placeholder!;
var col = 0;
for (final cluster in ph.characters) {
final cw = terminalCellWidth(cluster);
if (col + cw > width) break;
canvas.drawText(
cluster,
Offset(originX + col, originY),
dim,
background: _backgroundColor,
);
col += cw;
}
} else {
for (var row = 0; row < height; row++) {
final lineIdx = effectiveScrollLine + row;
if (lineIdx >= visualLayout.lines.length) break;
final line = visualLayout.lines[lineIdx];
var cellAccum = 0;
var paintedCol = 0;
paintLine:
for (final run in line.runs) {
for (final cluster in run.text.characters) {
final clusterWidth = terminalCellWidth(cluster);
if (cellAccum + clusterWidth <= effectiveScrollCell) {
cellAccum += clusterWidth;
continue;
}
// If a wide cluster straddles the left edge, drop it whole.
if (cellAccum < effectiveScrollCell) {
cellAccum += clusterWidth;
continue;
}
if (paintedCol + clusterWidth > width) break paintLine;
canvas.drawText(
cluster,
Offset(originX + paintedCol, originY + row),
_color,
background: _backgroundColor,
);
paintedCol += clusterWidth;
cellAccum += clusterWidth;
}
}
}
}
if (_focused) {
final cursorRow = cursor.row - effectiveScrollLine;
final cursorCell = _softWrap && width > 0 && cursor.cell >= width
? width - 1
: cursor.cell;
final cursorCol = cursorCell - effectiveScrollCell;
if (cursorRow >= 0 &&
cursorRow < height &&
cursorCol >= 0 &&
cursorCol < width) {
_cursorController.showCursor(
this,
originX + cursorCol,
originY + cursorRow,
style: _cursorStyle,
color: _cursorColor,
);
} else {
_cursorController.hideCursorFor(this);
}
} else {
_cursorController.hideCursorFor(this);
}
}