Files
dxfmakros/lib/elemente/omniflo_weichen.py
T

268 lines
8.8 KiB
Python

# omniflo_weichen.py
# Omniflo Weichen-Auswahl-Dialog (wx) und Weichen-Commands
# Ersetzt die Weichen-Teile von OmniModulInsert.lsp + omniflo_weichen.dcl
# ============================================
import wx
import PyRx as Rx
import PyDb as Db
import PyEd as Ed
from elemente.omniflo import (
load_weichen,
filter_by,
insert_from_entry,
sivasnr_to_str,
)
# ============================================================
# Weichen-Auswahl-Dialog (ersetzt omniflo_weichen.dcl)
# ============================================================
class WeichenSelectDialog(wx.Dialog):
"""Weichen-Auswahl-Dialog mit Filtern.
Layout:
- Dropdown: ProfilTyp (gefiltert)
- Filter-Gruppe Schaltungstyp: Alle / M / P (wx.RadioBox)
- Filter-Gruppe Richtung: Alle / Links / Rechts (wx.RadioBox)
- Detail-Felder (readonly): SivasNr, Winkel, Breite, Laenge
- OK / Abbrechen
"""
def __init__(self, parent, basis_liste):
super().__init__(parent, title="Omniflo Weiche auswaehlen",
size=(500, 320),
style=wx.DEFAULT_DIALOG_STYLE)
self._basis = basis_liste
self._gefiltert = list(basis_liste)
self._selected_idx = 0
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
# Dropdown: ProfilTyp
row_profil = wx.BoxSizer(wx.HORIZONTAL)
row_profil.Add(wx.StaticText(panel, label="Profiltyp:"), 0,
wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
self.cb_profil = wx.Choice(panel, choices=[])
self.cb_profil.Bind(wx.EVT_CHOICE, self._on_selection)
row_profil.Add(self.cb_profil, 1)
sizer.Add(row_profil, 0, wx.EXPAND | wx.ALL, 5)
# Filter-Gruppe: Schaltungstyp + Richtung nebeneinander
filter_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.rb_schaltung = wx.RadioBox(panel, label="Schaltungstyp",
choices=["Alle", "M", "P"],
majorDimension=1,
style=wx.RA_SPECIFY_COLS)
self.rb_schaltung.Bind(wx.EVT_RADIOBOX, self._apply_filter)
filter_sizer.Add(self.rb_schaltung, 1, wx.EXPAND | wx.RIGHT, 5)
self.rb_richtung = wx.RadioBox(panel, label="Richtung",
choices=["Alle", "Links", "Rechts"],
majorDimension=1,
style=wx.RA_SPECIFY_COLS)
self.rb_richtung.Bind(wx.EVT_RADIOBOX, self._apply_filter)
filter_sizer.Add(self.rb_richtung, 1, wx.EXPAND)
sizer.Add(filter_sizer, 0, wx.EXPAND | wx.ALL, 5)
# Detail-Felder (2 Spalten)
grid = wx.FlexGridSizer(cols=4, hgap=10, vgap=5)
grid.AddGrowableCol(1)
grid.AddGrowableCol(3)
grid.Add(wx.StaticText(panel, label="SivasNr:"), 0, wx.ALIGN_CENTER_VERTICAL)
self.txt_sivasnr = wx.TextCtrl(panel, style=wx.TE_READONLY, size=(140, -1))
grid.Add(self.txt_sivasnr, 0)
grid.Add(wx.StaticText(panel, label="Winkel:"), 0, wx.ALIGN_CENTER_VERTICAL)
self.txt_winkel = wx.TextCtrl(panel, style=wx.TE_READONLY, size=(100, -1))
grid.Add(self.txt_winkel, 0)
grid.Add(wx.StaticText(panel, label="Breite:"), 0, wx.ALIGN_CENTER_VERTICAL)
self.txt_breite = wx.TextCtrl(panel, style=wx.TE_READONLY, size=(100, -1))
grid.Add(self.txt_breite, 0)
grid.Add(wx.StaticText(panel, label="Laenge:"), 0, wx.ALIGN_CENTER_VERTICAL)
self.txt_laenge = wx.TextCtrl(panel, style=wx.TE_READONLY, size=(100, -1))
grid.Add(self.txt_laenge, 0)
sizer.Add(grid, 0, wx.EXPAND | wx.ALL, 5)
# OK / Cancel
btn_sizer = self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL)
sizer.Add(btn_sizer, 0, wx.EXPAND | wx.ALL, 10)
panel.SetSizer(sizer)
self.Fit()
self.CenterOnScreen()
# Initiale Befuellung
self._refresh_dropdown()
def _apply_filter(self, event=None):
"""Filter anwenden und Dropdown neu befuellen."""
self._refresh_dropdown()
def _refresh_dropdown(self):
"""Dropdown mit gefilterter Liste neu fuellen."""
sch_idx = self.rb_schaltung.GetSelection()
ri_idx = self.rb_richtung.GetSelection()
# Schaltungstyp-Filter
sch_filter = {0: None, 1: "M", 2: "P"}.get(sch_idx)
# Richtungs-Filter (1=links, 2=rechts)
ri_filter = {0: None, 1: 1, 2: 2}.get(ri_idx)
self._gefiltert = []
for e in self._basis:
if sch_filter and e.get("Schaltungstyp") != sch_filter:
continue
if ri_filter and e.get("KurvenRichtung") != ri_filter:
continue
self._gefiltert.append(e)
# Dropdown neu befuellen
self.cb_profil.Clear()
for e in self._gefiltert:
self.cb_profil.Append(e.get("ProfilTyp", "?"))
if self._gefiltert:
self.cb_profil.SetSelection(0)
self._selected_idx = 0
self._update_details(0)
else:
self._selected_idx = -1
self.txt_sivasnr.SetValue("---")
self.txt_winkel.SetValue("---")
self.txt_breite.SetValue("---")
self.txt_laenge.SetValue("---")
def _on_selection(self, event):
self._selected_idx = self.cb_profil.GetSelection()
self._update_details(self._selected_idx)
def _update_details(self, idx):
if idx < 0 or idx >= len(self._gefiltert):
return
e = self._gefiltert[idx]
self.txt_sivasnr.SetValue(sivasnr_to_str(e.get("Sivasnr")))
wkl = e.get("KurvenWinkel", 0)
self.txt_winkel.SetValue(f"{wkl} Grad")
self.txt_breite.SetValue(str(e.get("Breite", "?")))
self.txt_laenge.SetValue(str(e.get("Länge", "?")))
def get_selected(self):
"""Gewaehlten Weichen-Eintrag zurueckgeben."""
if 0 <= self._selected_idx < len(self._gefiltert):
return self._gefiltert[self._selected_idx]
return None
# ============================================================
# Generische Weichen-Einfuege-Logik
# ============================================================
def _weichen_command(winkel, weichentyp):
"""Weichen-Dialog oeffnen, Auswahl einfuegen."""
alle = load_weichen()
# Nach Winkel filtern (None = alle Winkel)
if winkel is not None:
basis = filter_by(alle, "KurvenWinkel", winkel)
else:
basis = list(alle)
# Nach WeichenTyp filtern
if weichentyp:
basis = [e for e in basis if e.get("WeichenTyp") == weichentyp]
if not basis:
wkl_str = "alle Winkel" if winkel is None else f"{winkel} Grad"
typ_str = f" / {weichentyp}" if weichentyp else ""
print(f"\nKeine Weichen fuer {wkl_str}{typ_str} gefunden.")
return
dlg = WeichenSelectDialog(None, basis)
if dlg.ShowModal() == wx.ID_OK:
eintrag = dlg.get_selected()
dlg.Destroy()
if eintrag:
insert_from_entry(eintrag)
else:
print("\n[WEICHE] Kein Eintrag ausgewaehlt.")
else:
dlg.Destroy()
print("\n[WEICHE] Abgebrochen.")
# ============================================================
# Weichen-Commands (gleiche Namen wie LISP)
# ============================================================
# --- 90 Grad ---
@Rx.command("OMNI_W90_Einfach")
def cmd_w90_einfach():
_weichen_command(90, "Einzelweiche")
@Rx.command("OMNI_W90_Doppel")
def cmd_w90_doppel():
_weichen_command(90, "Doppelweiche")
@Rx.command("OMNI_W90_Dreiwege")
def cmd_w90_dreiwege():
_weichen_command(90, "Dreiwegeweiche")
# --- 45 Grad ---
@Rx.command("OMNI_W45_Einfach")
def cmd_w45_einfach():
_weichen_command(45, "Einzelweiche")
@Rx.command("OMNI_W45_Doppel")
def cmd_w45_doppel():
_weichen_command(45, "Doppelweiche")
@Rx.command("OMNI_W45_Dreiwege")
def cmd_w45_dreiwege():
_weichen_command(45, "Dreiwegeweiche")
# --- Parallel (KurvenWinkel=0) ---
@Rx.command("OMNI_WP_Einfach")
def cmd_wp_einfach():
_weichen_command(0, "Einzelweiche")
@Rx.command("OMNI_WP_Doppel")
def cmd_wp_doppel():
_weichen_command(0, "Doppelweiche")
@Rx.command("OMNI_WP_Dreiwege")
def cmd_wp_dreiwege():
_weichen_command(0, "Dreiwegeweiche")
# --- Weichenkoerper (KurvenWinkel=22.5) ---
@Rx.command("OMNI_WK_Einfach")
def cmd_wk_einfach():
_weichen_command(22.5, "Einzelweiche")
@Rx.command("OMNI_WK_Doppel")
def cmd_wk_doppel():
_weichen_command(22.5, "Doppelweiche")
@Rx.command("OMNI_WK_Dreiwege")
def cmd_wk_dreiwege():
_weichen_command(22.5, "Dreiwegeweiche")
# --- Weichenkombinationen ---
@Rx.command("OMNI_WKomb_Delta")
def cmd_wkomb_delta():
_weichen_command(None, "Deltaweiche")
@Rx.command("OMNI_WKomb_Star")
def cmd_wkomb_star():
_weichen_command(None, "Sternweiche")