view method

  1. @override
Object view()
override

Renders the current model state for display.

This method is called after every update to refresh the screen. It should return either a String or a View object.

Guidelines

  • Keep view functions pure - no side effects
  • View should only depend on model state
  • Use string interpolation or StringBuffer for complex views
  • Consider terminal width/height for responsive layouts

Example

@override
String view() {
  final buffer = StringBuffer();

  // Header
  buffer.writeln('╔════════════════════════════╗');
  buffer.writeln('║      My Application        ║');
  buffer.writeln('╚════════════════════════════╝');
  buffer.writeln();

  // Content
  if (loading) {
    buffer.writeln('Loading...');
  } else {
    for (final item in items) {
      final prefix = item == selectedItem ? '▸ ' : '  ';
      buffer.writeln('$prefix$item');
    }
  }

  buffer.writeln();

  // Footer
  buffer.writeln('↑/↓: Navigate  Enter: Select  q: Quit');

  return buffer.toString();
}

Implementation

@override
Object view() {
  final preRenderBackgroundColor = _resolveTerminalBackgroundColor(
    backgroundColorBuilder?.call() ?? backgroundColor,
  );
  final backgroundChanged =
      preRenderBackgroundColor != _cachedBackgroundColor;

  final canReuseCachedBase =
      !_dirty && !_tree.hasPaintDirty && _cachedView != null;

  if (!_dirty &&
      !backgroundChanged &&
      !_overlayDirty &&
      _cachedViewObject != null &&
      !_tree.hasPaintDirty) {
    if (TuiTrace.enabled) {
      TuiTrace.log('widget_view cache hit');
    }
    return _cachedViewObject!;
  }

  late String baseContent;
  if (canReuseCachedBase) {
    baseContent = _cachedView!;
  } else {
    final Stopwatch? sw = TuiTrace.enabled ? Stopwatch() : null;
    sw?.start();
    baseContent = _tree.render();
    sw?.stop();
    if (sw != null) {
      TuiTrace.log('widget_view render ${sw.elapsedMicroseconds}us');
    }

    _cachedView = baseContent;
    _dirty = false;
  }

  _recordAndPublishKeyRenderLatency();

  var composedContent = baseContent;
  if (_debugOverlayEnabled) {
    composedContent = _runtimeDebugOverlay.compose(baseContent);
  }

  final resolvedBackgroundColor = _resolveTerminalBackgroundColor(
    backgroundColorBuilder?.call() ?? backgroundColor,
  );
  _cachedBackgroundColor = resolvedBackgroundColor;
  _overlayDirty = false;

  if (resolvedBackgroundColor != null) {
    final viewObj = View(
      content: composedContent,
      backgroundColor: resolvedBackgroundColor,
    );
    _cachedViewObject = viewObj;
    return viewObj;
  }
  _cachedViewObject = composedContent;
  return composedContent;
}