Source code for fieldview.layout

"""Layout management helpers for interactive or batch FieldView sessions.

The functions in this module operate on graphics windows within the current
FieldView layout. Window numbers are 1-based and match the numbering used by
the host UI. The current window is the default target whenever an operation
accepts ``window=None``.

Use :mod:`fieldview.layout` when you need to inspect the current pane layout,
switch the active window, split a view into additional panes, close panes, or
configure multi-window view synchronization.

Example:

.. code-block:: python

    >>> import os
    >>> import fieldview as fv
    >>> data_dir = os.path.join(fv.home, "examples", "f18")
    >>> ds = fv.data.load_plot3d(
    ...     os.path.join(data_dir, "f18i9b_g_bin"),
    ...     os.path.join(data_dir, "f18i9b_q_bin"),
    ... )
    >>> split = fv.layout.split_vertical(mode="copy")
    >>> fv.layout.select(split.new_window)
"""

from __future__ import annotations

from typing import cast

from ._core_utils import _core_call, _normalize_window, _require_core_func
from .data import (
    WindowList,
    WindowSplitResult,
    _build_window_list,
    _build_window_split_result,
)
from .exceptions import CoreError, InvalidArgumentError

__all__ = [
    "get_windows",
    "current",
    "select",
    "split_vertical",
    "split_horizontal",
    "get_view_sync",
    "set_view_sync",
    "close",
]


def _normalize_mode(mode: str) -> str:
    if not isinstance(mode, str):
        raise InvalidArgumentError("mode must be a string")
    lowered = mode.strip().lower()
    if lowered not in {"copy", "instance", "empty"}:
        raise InvalidArgumentError("mode must be 'copy', 'instance', or 'empty'")
    return lowered


[docs] def get_windows() -> WindowList: """Return metadata for all graphics windows in the current layout. This works in both interactive and batch graphics sessions. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> windows = fv.layout.get_windows() """ func = _require_core_func("get_windows") windows = _build_window_list(cast(dict[str, object], _core_call(func))) if windows is None: raise CoreError("get_windows returned invalid payload.") return windows
[docs] def current() -> int: """Return the 1-based number of the current graphics window. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> window = fv.layout.current() """ windows = get_windows() if windows.current_window is None: raise CoreError("No current window is available.") return windows.current_window
[docs] def select(window: int) -> None: """Make ``window`` the current graphics window. Args: window: 1-based graphics window number to select. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> split = fv.layout.split_vertical(mode="copy") >>> fv.layout.select(split.source_window) """ func = _require_core_func("select_window") _core_call(func, _normalize_window(window))
[docs] def split_vertical(mode: str = "copy", window: int | None = None) -> WindowSplitResult: """Split a window vertically and return metadata for the new window. ``window=None`` targets the current window. The new window becomes current on success. Args: mode: Split mode, one of ``copy``, ``instance``, or ``empty``. window: Optional 1-based source window number. When omitted, the current graphics window is split. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> split = fv.layout.split_vertical(mode="copy") """ func = _require_core_func("split_window_vertical") resp = cast( dict[str, object], _core_call(func, _normalize_mode(mode), _normalize_window(window)), ) return _build_window_split_result(resp)
[docs] def split_horizontal( mode: str = "copy", window: int | None = None ) -> WindowSplitResult: """Split a window horizontally and return metadata for the new window. ``window=None`` targets the current window. The new window becomes current on success. Args: mode: Split mode, one of ``copy``, ``instance``, or ``empty``. window: Optional 1-based source window number. When omitted, the current graphics window is split. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> split = fv.layout.split_horizontal(mode="copy") """ func = _require_core_func("split_window_horizontal") resp = cast( dict[str, object], _core_call(func, _normalize_mode(mode), _normalize_window(window)), ) return _build_window_split_result(resp)
[docs] def close(window: int | None = None) -> None: """Close a graphics window. ``window=None`` closes the current window. When the current child window is closed, FieldView selects its parent window. Args: window: Optional 1-based window number to close. When omitted, the current graphics window is closed. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> split = fv.layout.split_vertical(mode="copy") >>> fv.layout.close(split.new_window) """ func = _require_core_func("close_window") _core_call(func, _normalize_window(window))
[docs] def get_view_sync(window: int | None = None) -> bool: """Return whether a window propagates view/camera changes to synced panes. ``window=None`` targets the current window. Args: window: Optional 1-based window number. When omitted, the current graphics window is used. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> enabled = fv.layout.get_view_sync() """ func = _require_core_func("get_window_view_sync") return bool(_core_call(func, _normalize_window(window)))
[docs] def set_view_sync(enabled: bool, window: int | None = None) -> None: """Enable or disable multi-window view syncing for a graphics window. ``window=None`` targets the current window. Args: enabled: Whether view/camera synchronization should be enabled for the target window. window: Optional 1-based window number. When omitted, the current graphics window is used. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> split = fv.layout.split_vertical(mode="copy") >>> fv.layout.set_view_sync(True, window=split.source_window) >>> fv.layout.set_view_sync(True, window=split.new_window) """ if not isinstance(enabled, bool): raise InvalidArgumentError("enabled must be a boolean") func = _require_core_func("set_window_view_sync") _core_call(func, enabled, _normalize_window(window))