render method

  1. @override
void render(
  1. Rect area,
  2. Buffer buffer,
  3. RenderContext ctx
)
override

Implementation

@override
void render(Rect area, Buffer buffer, RenderContext ctx) {
  if (area.isEmpty) return;
  final focused = ctx.isFocused(id);
  final visible = _flatten();
  if (visible.isEmpty) return;
  state.activeIndex = state.activeIndex.clamp(0, visible.length - 1);

  // Keep active in viewport.
  if (state.activeIndex < state.scrollOffset) {
    state.scrollOffset = state.activeIndex;
  } else if (state.activeIndex >= state.scrollOffset + area.height) {
    state.scrollOffset = state.activeIndex - area.height + 1;
  }
  state.scrollOffset = state.scrollOffset.clamp(0, visible.length);

  final base = itemStyle ?? ctx.theme.text.body;
  final activeS = activeStyle ??
      Style(
        fg: ctx.theme.colors.background,
        bg: focused ? ctx.theme.colors.primary : ctx.theme.colors.foreground,
        bold: true,
      );
  final icon = iconStyle ?? Style(fg: ctx.theme.colors.muted);

  for (var row = 0; row < area.height; row++) {
    final idx = state.scrollOffset + row;
    if (idx >= visible.length) break;
    final v = visible[idx];
    final y = area.y + row;
    final isActive = idx == state.activeIndex;

    final iconChar = v.node.isLeaf
        ? leafIcon
        : (state.expanded.contains(v.key) ? expandedIcon : collapsedIcon);

    final prefix = ' ' * (v.depth * indent);
    final line = '$prefix$iconChar ${v.node.label}';

    // Background fill for active row.
    if (isActive) {
      for (var i = 0; i < area.width; i++) {
        buffer.setChar(area.x + i, y, ' ', style: activeS);
      }
    }

    // Icon
    final iconX = area.x + prefix.length;
    if (iconX < area.right) {
      buffer.writeText(iconX, y, iconChar,
          style: isActive ? activeS : icon, maxWidth: area.right - iconX);
    }
    // Label
    final lblX = iconX + iconChar.length + 1;
    if (lblX < area.right) {
      buffer.writeText(lblX, y, v.node.label,
          style: isActive ? activeS : base, maxWidth: area.right - lblX);
    }
    // Suppress unused
    if (line.isEmpty) {}
  }
}