focusByDirection method

TilingPaneManager focusByDirection({
  1. required PaneNavigationDirection direction,
  2. required int width,
  3. required int height,
})

Focuses the nearest neighboring pane in the requested direction.

Implementation

TilingPaneManager focusByDirection({
  required PaneNavigationDirection direction,
  required int width,
  required int height,
}) {
  if (!isValid) {
    return this;
  }

  final layout = this.layout(width: width, height: height);
  final focused = layout.panes[focusedPaneId];
  if (focused == null) return this;

  String? nextId;
  int bestScore = -1;
  int bestDistance = math.max(width, height) + 1;

  for (final entry in layout.panes.entries) {
    if (entry.key == focusedPaneId) continue;
    final candidate = entry.value;
    if (!_isAdjacent(focused, candidate, direction)) continue;

    final score =
        direction == PaneNavigationDirection.left ||
            direction == PaneNavigationDirection.right
        ? _overlapLength(
            focused.y,
            focused.height,
            candidate.y,
            candidate.height,
          )
        : _overlapLength(
            focused.x,
            focused.width,
            candidate.x,
            candidate.width,
          );

    if (score == 0) continue;
    final distance = switch (direction) {
      PaneNavigationDirection.left =>
        focused.x - (candidate.x + candidate.width),
      PaneNavigationDirection.right =>
        candidate.x - (focused.x + focused.width),
      PaneNavigationDirection.up =>
        focused.y - (candidate.y + candidate.height),
      PaneNavigationDirection.down =>
        candidate.y - (focused.y + focused.height),
    };

    if (score > bestScore ||
        (score == bestScore && distance < bestDistance)) {
      bestScore = score;
      bestDistance = distance;
      nextId = entry.key;
    }
  }

  if (nextId == null) return this;
  return copyWith(focusedPaneId: nextId);
}