onUpdate method

  1. @override
  2. @mustCallSuper
void onUpdate(
  1. double dt
)
override

Override to react during the update phase each frame.

Called after all registered listenOnUpdate listeners.

Implementation

@override
@mustCallSuper
void onUpdate(double dt) => on2<CTransform<T>, CRectCollider<T>>((t, c) {
  t.position = worldPosition;
  // collider covers only the trigger; dropdown is handled manually
  c.size = _interactiveSize.copy();

  final mouse = backend.mouse;
  final origin = t.position;

  final RectangleD triggerRect = .rect(origin.x, origin.y, controlWidth, controlHeight);

  final hoveredTrigger = backend.collision.pointRectangle(
    mouse.position, triggerRect,
  );

  _IsWidgetClickable_updateState(
    hovered: hoveredTrigger,
    usePendingSingleClickMethod: false,
    dt: dt,
  );

  // toggle open on trigger click
  if (hoveredTrigger && mouse.btnLeft.pressed) {
    _isOpen = !_isOpen;
    _hoveredItemIndex = -1;
  }

  if (_isOpen) {
    final RectangleD dropdownRect = .rect(
      origin.x, origin.y + controlHeight,
      controlWidth, _dropdownHeight,
    );

    final hoveredDropdown = backend.collision.pointRectangle(
      mouse.position, dropdownRect,
    );

    // track which item the mouse is over
    if (hoveredDropdown) {
      final relY = mouse.position.y - (origin.y + controlHeight);
      _hoveredItemIndex = (relY / itemHeight).floor().clamp(0, options.length - 1);
    } else {
      _hoveredItemIndex = -1;
    }

    // click an item
    if (hoveredDropdown && mouse.btnLeft.pressed) {
      selectedIndex = _hoveredItemIndex;
      onChangeFn?.call(this, selectedIndex, selectedLabel);
      _isOpen = false;
      _hoveredItemIndex = -1;
    }

    // click outside the entire widget → close
    final hoveredFull = backend.collision.pointRectangle(
      mouse.position, _fullRect(origin),
    );
    if (!hoveredFull && mouse.btnLeft.pressed) {
      _isOpen = false;
      _hoveredItemIndex = -1;
    }

    // keyboard navigation
    if (backend.input.isKeyPressed(.KEY_ESCAPE)) {
      _isOpen = false;
      _hoveredItemIndex = -1;
    }
    if (backend.input.isKeyPressed(.KEY_DOWN)) {
      _hoveredItemIndex = (_hoveredItemIndex + 1).clamp(0, options.length - 1);
    }
    if (backend.input.isKeyPressed(.KEY_UP)) {
      _hoveredItemIndex = (_hoveredItemIndex - 1).clamp(0, options.length - 1);
    }
    if (backend.input.isKeyPressed(.KEY_ENTER) || backend.input.isKeyPressed(.KEY_KP_ENTER)) {
      if (_hoveredItemIndex >= 0) {
        selectedIndex = _hoveredItemIndex;
        onChangeFn?.call(this, selectedIndex, selectedLabel);
      }
      _isOpen = false;
      _hoveredItemIndex = -1;
    }
  }
});