Source code for wolfhece._dike_manager

"""Dike companion object for WolfMapViewer.

All dike-simulation management logic lives here (DikeWolf objects, menu,
event dispatch, creation).  Injectors are *not* part of this companion —
they register themselves via ``WolfMapViewer.add_object(which='injector')``
when ``DikeWolf.set_injector()`` is called.

``WolfMapViewer`` holds a single instance as ``self._dike = DikeManager(self)``
and exposes one-line delegators so that external callers remain unaffected.
"""
from __future__ import annotations

import logging
from enum import Enum
from typing import TYPE_CHECKING

import wx

from .PyTranslate import _

try:
    from .dike import DikeWolf
    _AVAILABLE = True
except Exception:
    _AVAILABLE = False

if TYPE_CHECKING:
    from .PyDraw import WolfMapViewer

__all__ = ['DikeManager']


[docs] class DikeManager: """Companion object that owns dike-simulation state. Instantiated unconditionally as ``viewer._dike = DikeManager(viewer)`` inside ``WolfMapViewer.__init__``. If the *wolfpydike* package is not installed, ``available`` is ``False`` and all operations are no-ops or log an error. """
[docs] available: bool = _AVAILABLE
def __init__(self, viewer: 'WolfMapViewer') -> None:
[docs] self._viewer = viewer
# ── Object registry ──────────────────────────────────────────────
[docs] self.mydikes: list['DikeWolf'] = []
[docs] self.active: 'DikeWolf | None' = None
# ── Menu state (lazy-built) ───────────────────────────────────────
[docs] self._menu: wx.Menu | None = None
# ------------------------------------------------------------------ # Object registration (called by WolfMapViewer.add_object) # ------------------------------------------------------------------
[docs] def register(self, newobj: 'DikeWolf') -> None: """Add *newobj* to the registry and make it the active dike.""" self.mydikes.append(newobj) self.active = newobj
# ------------------------------------------------------------------ # Menu construction (idempotent) # ------------------------------------------------------------------
[docs] def menu_build(self) -> None: """Create and append the 'Dike' menu to the viewer menubar. Safe to call multiple times — only the first call has any effect. Silently returns if wolfpydike is not available. """ if not _AVAILABLE: return if self._menu is not None: return viewer = self._viewer self._menu = wx.Menu() item_lumped = self._menu.Append(wx.ID_ANY, _("Launch lumped simulation"), _("Launch lumped simulation")) self._menu.AppendSeparator() item_injector = self._menu.Append(wx.ID_ANY, _("Set injector"), _("Set injector")) item_coupled = self._menu.Append(wx.ID_ANY, _("Launch 2D-coupled simulation"),_("Launch 2D-coupled simulation")) self._menu.AppendSeparator() item_triang = self._menu.Append(wx.ID_ANY, _("Show triangulation"), _("Show triangulation")) item_discharge = self._menu.Append(wx.ID_ANY, _("Plot discharges"), _("Plot discharges")) item_levels = self._menu.Append(wx.ID_ANY, _("Plot water levels/breach bottom"), _("Plot water levels/breach bottom")) item_breach = self._menu.Append(wx.ID_ANY, _("Plot breach width"), _("Plot breach width")) self._menu.AppendSeparator() item_params = self._menu.Append(wx.ID_ANY, _("Show parameters"), _("Show parameters")) viewer.menubar.Append(self._menu, _('Dike')) self._menu.Bind(wx.EVT_MENU, self._on_lumped, item_lumped) self._menu.Bind(wx.EVT_MENU, self._on_injector, item_injector) self._menu.Bind(wx.EVT_MENU, self._on_coupled, item_coupled) self._menu.Bind(wx.EVT_MENU, self._on_triang, item_triang) self._menu.Bind(wx.EVT_MENU, self._on_discharge, item_discharge) self._menu.Bind(wx.EVT_MENU, self._on_levels, item_levels) self._menu.Bind(wx.EVT_MENU, self._on_breach, item_breach) self._menu.Bind(wx.EVT_MENU, self._on_params, item_params)
# ------------------------------------------------------------------ # Menu event handler # ------------------------------------------------------------------
[docs] def _active_guard(self) -> bool: """Return True if available and active dike exists, log and return False otherwise.""" if not _AVAILABLE: logging.error('WolfPyDike not installed — please install wolfpydike via pip') return False if self.active is None: logging.warning(_('No active dike -- Please activate a dike first')) return False return True
[docs] def _on_lumped(self, event: wx.MenuEvent) -> None: if self._active_guard(): self.active.run_lumped()
[docs] def _on_injector(self, event: wx.MenuEvent) -> None: if self._active_guard(): self.active.set_injector()
[docs] def _on_coupled(self, event: wx.MenuEvent) -> None: if self._active_guard(): self.active.run_2Dcoupled()
[docs] def _on_triang(self, event: wx.MenuEvent) -> None: if self._active_guard(): self.active.show_triangulation()
[docs] def _on_discharge(self, event: wx.MenuEvent) -> None: if self._active_guard(): self.active.plot_mainOutputs(0)
[docs] def _on_levels(self, event: wx.MenuEvent) -> None: if self._active_guard(): self.active.plot_mainOutputs(1)
[docs] def _on_breach(self, event: wx.MenuEvent) -> None: if self._active_guard(): self.active.plot_mainOutputs(2)
[docs] def _on_params(self, event: wx.MenuEvent) -> None: if self._active_guard(): self.active.show_properties()
# ------------------------------------------------------------------ # Object creation (called by WolfMapViewer menu handlers) # ------------------------------------------------------------------
[docs] def new_dike(self, itemlabel: str) -> None: """Handle 'Create dike...' and 'Add dike...' menu items.""" if not _AVAILABLE: logging.error('WolfPyDike not installed — please install wolfpydike via pip') return viewer = self._viewer newobj = DikeWolf(mapviewer=viewer) if _('Add dike...') in itemlabel: try: newobj.load_results() except Exception: logging.error(_('Error in loading dike results - Aborting !')) return viewer.add_object(which='dike', newobj=newobj, ToCheck=True) self.menu_build()