update method

({Cmd? cmd, bool consumed, DebugOverlayModel model}) update(
  1. Msg msg
)

Updates overlay state and reports whether the message was consumed.

Implementation

({DebugOverlayModel model, Cmd? cmd, bool consumed}) update(Msg msg) {
  switch (msg) {
    case RenderMetricsMsg(:final metrics):
      return (model: copyWith(metrics: metrics), cmd: null, consumed: false);

    case WindowSizeMsg(:final width, :final height):
      final next = copyWith(terminalWidth: width, terminalHeight: height);
      // Clamp stored position if set.
      if (next.panelX != null || next.panelY != null) {
        final (:x, :y, :w, :h) = next._panelRect();
        final clampedX = x.clamp(0, (width - w).clamp(0, width));
        final clampedY = y.clamp(0, (height - h).clamp(0, height));
        return (
          model: next.copyWith(panelX: clampedX, panelY: clampedY),
          cmd: null,
          consumed: false,
        );
      }
      return (model: next, cmd: null, consumed: false);

    case MouseMsg(:final x, :final y, :final button, :final action):
      if (!enabled) return (model: this, cmd: null, consumed: false);

      // When dragging, consume ALL mouse events to prevent selection bleed.
      if (dragging) {
        if (action == MouseAction.release) {
          return (
            model: copyWith(dragging: false),
            cmd: null,
            consumed: true,
          );
        }
        if (action == MouseAction.motion) {
          // Use fixed panel dimensions to avoid expensive re-render during drag
          const panelHeight = 8; // 6 content lines + 2 border lines
          final maxX = (terminalWidth - panelWidth).clamp(0, terminalWidth);
          final maxY = (terminalHeight - panelHeight).clamp(
            0,
            terminalHeight,
          );
          final nx = (x - dragOffsetX).clamp(0, maxX);
          final ny = (y - dragOffsetY).clamp(0, maxY);
          return (
            model: copyWith(panelX: nx, panelY: ny),
            cmd: null,
            consumed: true,
          );
        }
        return (model: this, cmd: null, consumed: true);
      }

      // Start dragging when clicking inside the panel.
      if (action == MouseAction.press && button == MouseButton.left) {
        // Use approximate bounds for hit testing (avoids rendering panel)
        const panelHeight = 8;
        final px = panelX ?? (terminalWidth - panelWidth - marginRight);
        final py = panelY ?? (terminalHeight - panelHeight - marginBottom);
        final inPanel =
            x >= px && x < px + panelWidth && y >= py && y < py + panelHeight;
        if (inPanel) {
          return (
            model: copyWith(
              dragging: true,
              dragOffsetX: x - px,
              dragOffsetY: y - py,
            ),
            cmd: null,
            consumed: true,
          );
        }
      }

      return (model: this, cmd: null, consumed: false);

    default:
      return (model: this, cmd: null, consumed: false);
  }
}