From 43896a28f5742ee962552a7ee4a03bc5c7cd1408 Mon Sep 17 00:00:00 2001 From: Michael Stangl Date: Thu, 27 Aug 2026 17:50:47 +0200 Subject: [PATCH] VF-Linienzug: Einzelsegment-Bearbeitung (GF-Bogen) + punktfreies Journal Doppelklick auf einen Linienzug-VF_n-Block bietet jetzt zwei Modi (neuer Dialog vfl_edit_modus.dcl / vfl-dlg-modus): auf eine Sektion zuruecksetzen (bisheriges Verhalten) ODER die Eigenschaften EINES einzelnen Glieds aendern (vfl-edit-glied). Fuer GF-Boegen laesst sich Winkel (30/60/90) und Seite (links/rechts) direkt aendern; das Glied wird per vfl-journal-splice im Ketten-Journal ersetzt und die komplette Kette 1:1 neu aufgebaut. Damit die nachfolgenden Glieder nach einer Bogen-Aenderung korrekt neu verketten, speichert das Journal fuer Linien-Segmente jetzt nur noch die relative Distanz (deltaL, neuer Journal-Kind "DL") statt eines absoluten Punkts - nur der Kettenstartpunkt bleibt ein echter Punkt. Richtung wird ohnehin vom Vorgaenger-Frame geerbt (nur das erste Segment journalisiert zusaetzlich die gesnappte Richtung). vfl-in-abstand ersetzt die punktbasierte Messung in vfl-neue-linie-messen; vfl-kettenanfang-baustein rechnet die AS-Restlaenge rein skalar (kein pick-punkt mehr). Wichtige Korrekturen: - vfl-entry->string/-entry kannten den DL-Kind nicht (wurde als NIL serialisiert -> Distanzverlust beim erneuten Lesen) - vfl-in-abstand journalisiert jetzt in BEIDEN Zweigen (Replay UND Live), wie die anderen vfl-in-*-Wrapper - sonst gingen die DL-Werte replizierter Glieder beim erneuten Speichern verloren (2. Edit stuerzte ab) Diagnose: komplettes Journal wird beim Erzeugen (XDATA-JOURNAL-JSON) und zu Beginn eines Replays (REPLAY-QUEUE-JSON) als JSON in die Debug-Datei geschrieben (No-Op ohne aktiven Debug-Schalter). dcl/vfl_edit.dcl: Popup breiter (edit_width/list_width), damit lange Sektionstexte nicht abgeschnitten werden. Co-Authored-By: Claude Opus 4.8 (1M context) --- Lisp/vf_linienzug.lsp | 533 +++++++++++++++++++++++++++++++++++------ dcl/vfl_edit.dcl | 4 +- dcl/vfl_edit_modus.dcl | 45 ++++ lang/de_DE.json | 6 + lang/en_GB.json | 6 + 5 files changed, 526 insertions(+), 68 deletions(-) create mode 100644 dcl/vfl_edit_modus.dcl diff --git a/Lisp/vf_linienzug.lsp b/Lisp/vf_linienzug.lsp index 2454cff..d8c227f 100644 --- a/Lisp/vf_linienzug.lsp +++ b/Lisp/vf_linienzug.lsp @@ -486,12 +486,12 @@ ;; ------------------------------------------------------------ ;; Gruppe "Gefaelle festlegen" (Linie GF): Modus(Hoehe/Winkel) + EIN -;; Wertfeld (Beschriftung wechselt mit dem Modus). KEIN Punkt-Feld: der -;; Endpunkt (X/Y, fuer die Fahrtrichtung/Laengenberechnung) ist an der -;; Aufrufstelle bereits VOR dieser Gruppe ueber vfl-neue-linie-messen/ -;; vfl-in-point gepickt - dessen Z wird nie gelesen, "Hoehe" hier ist ein -;; davon unabhaengiger Zahlenwert (siehe Kommentar bei -;; vfl-neue-linie-messen). Original-Reihenfolge/-Journal ab hier: +;; Wertfeld (Beschriftung wechselt mit dem Modus). KEIN Punkt-Feld: die +;; Laenge/Fahrtrichtung ist an der Aufrufstelle bereits VOR dieser Gruppe +;; ueber vfl-neue-linie-messen/vfl-in-abstand als deltaL/hz ermittelt (nur +;; noch ein Skalarpaar, kein Punkt mehr - siehe Kommentar bei +;; vfl-in-abstand) - dessen Z-Konzept existiert nicht mehr, "Hoehe" hier ist +;; ein eigener, unabhaengiger Zahlenwert. Original-Reihenfolge/-Journal ab hier: ;; vfl-in-string (Modus), danach vfl-in-real (Winkel ODER Hoehe). (defun vflw-gruppe-gefaelle-impl (hoehe-default / dat dcl-pfad ergebnis gmodus gwert winkel-default) (setq winkel-default (ssg-cfg-or "vario" "gefaelle_winkel" 3)) @@ -530,9 +530,9 @@ ;; ------------------------------------------------------------ ;; Gruppe "Ziel-Hoehe": NUR die Hoehen-Zahl (kein Punkt-Feld). Wiederverwendet ;; an mehreren Stellen (Linie-VF, VF-Einheit-Fortsetzung "Auf/Ab", -;; vfl-body-abschluss). Der Endpunkt (X/Y, fuer die Segmentlaenge) ist an der -;; Aufrufstelle bereits separat ueber vfl-neue-linie-messen gepickt - dessen -;; Z wird nirgends verwendet, die Hoehe hier ist eine davon unabhaengige +;; vfl-body-abschluss). Die Segmentlaenge ist an der Aufrufstelle bereits +;; separat ueber vfl-neue-linie-messen/vfl-in-abstand als deltaL (Skalar, +;; kein Punkt mehr) ermittelt - die Hoehe hier ist eine davon unabhaengige ;; Zahl (Default = aktuelle Kettenhoehe, wie im Original-Prompt). Nutzt ;; bewusst den generischen Einzel-Dialog vflw_zahl (kein Punkt-Button, der ;; faelschlich eine hier moegliche Punktwahl suggerieren wuerde). @@ -795,6 +795,7 @@ ((= k "PT") (strcat "PT:" (rtos (car v) 2 6) "," (rtos (cadr v) 2 6) "," (rtos (caddr v) 2 6))) ((= k "REAL") (strcat "REAL:" (rtos v 2 6))) + ((= k "DL") (strcat "DL:" (rtos v 2 6))) ((= k "INT") (strcat "INT:" (itoa v))) ((= k "STR") (strcat "STR:" v)) ((= k "STEP") (strcat "STEP:" v)) @@ -811,13 +812,54 @@ (setq c (vfl-strsplit pay ",")) (cons "PT" (list (atof (nth 0 c)) (atof (nth 1 c)) (atof (nth 2 c))))) ((= kind "REAL") (cons "REAL" (atof pay))) + ((= kind "DL") (cons "DL" (atof pay))) ((= kind "INT") (cons "INT" (atoi pay))) ((= kind "STR") (cons "STR" pay)) ((= kind "STEP") (cons "STEP" pay)) ((= kind "OBJS") (cons "OBJS" (if (> (strlen pay) 0) (vfl-strsplit pay ",") nil))) (t (cons "NIL" nil)))))) +;; forward-journal ist bereits in Bau-Reihenfolge (nicht die umgekehrte +;; *vfl-journal*-Rohform) - gemeinsame Serialisierung fuer Ketten- UND +;; Segment-XDATA (vfl-journal-xdata-schreiben / vfl-journal-xdata-schreiben-seg). +(defun vfl-journal-list->string (forward-journal) + (vfl-strjoin (mapcar 'vfl-entry->string forward-journal) "\n")) (defun vfl-journal->string () - (vfl-strjoin (mapcar 'vfl-entry->string (reverse *vfl-journal*)) "\n")) + (vfl-journal-list->string (reverse *vfl-journal*))) + +;; --- JSON-Dump des Journals fuer die Debug-Datei (nur Diagnose) --- +;; Wandelt EINEN Journal-Eintrag (kind . value) in ein JSON-Objekt +;; {"kind":"PT","value":[x,y,z]} um. String-Werte werden gequotet (mit +;; einfachem Escaping fuer " und \), Zahlen unquotiert, PT als Zahlen-Array, +;; OBJS als String-Array, NIL als null. Rein additive Diagnose - beruehrt die +;; XDATA-Serialisierung (vfl-entry->string) NICHT. +(defun vfl-json-escape (s / out c i n) + (setq out "" i 1 n (strlen s)) + (while (<= i n) + (setq c (substr s i 1)) + (setq out (strcat out (cond ((= c "\"") "\\\"") ((= c "\\") "\\\\") (t c)))) + (setq i (1+ i))) + out) +(defun vfl-json-num (x) (rtos x 2 6)) ; einheitliches Zahlformat (wie vfl-entry->string) +(defun vfl-entry->json (e / k v) + (setq k (car e) v (cdr e)) + (strcat "{\"kind\":\"" k "\",\"value\":" + (cond + ((null v) "null") + ((= k "PT") (strcat "[" (vfl-json-num (car v)) "," (vfl-json-num (cadr v)) "," + (vfl-json-num (caddr v)) "]")) + ((= k "REAL") (vfl-json-num v)) + ((= k "DL") (vfl-json-num v)) + ((= k "INT") (itoa v)) + ((= k "STR") (strcat "\"" (vfl-json-escape v) "\"")) + ((= k "STEP") (strcat "\"" (vfl-json-escape v) "\"")) + ((= k "OBJS") (strcat "[" (vfl-strjoin + (mapcar (function (lambda (h) (strcat "\"" (vfl-json-escape h) "\""))) + v) ",") "]")) + (t "null")) + "}")) +;; forward-journal (Bau-Reihenfolge) als kompakter JSON-Array-String. +(defun vfl-journal->json (forward-journal) + (strcat "[" (vfl-strjoin (mapcar 'vfl-entry->json forward-journal) ",") "]")) (defun vfl-string->journal (s / out) (setq out '()) (foreach ln (vfl-strsplit s "\n") @@ -843,6 +885,12 @@ (defun vfl-journal-xdata-schreiben (ent marker / chunks appentry) (if (null *vf-xdata-app*) (setq *vf-xdata-app* "SSG_VF_EDIT")) (regapp *vf-xdata-app*) + ;; Diagnose: komplettes Journal beim Erzeugen der Geometrie als JSON in die + ;; Debug-Datei (No-Op ohne offene .dbg-Datei, siehe dbgmsg). marker + JSON- + ;; Array der Eintraege in Bau-Reihenfolge. + (dbgmsg (strcat "XDATA-GESCHRIEBEN marker=" marker)) + (dbgmsg (strcat "XDATA-JOURNAL-JSON " (vfl-journal->json (reverse *vfl-journal*)))) + (dbgflush) (setq chunks (vfl-chunk-string (vfl-journal->string) 250)) (setq appentry (cons *vf-xdata-app* @@ -857,6 +905,67 @@ (cons (car xd) (vfl-string->journal (apply 'strcat (cdr xd)))) nil)) +;; --- Segment-XDATA (pro einzelnem Glied-Entity, eigener App-Name) --- +;; Eigene App "SSG_VF_EDIT_SEG" statt SSG_VF_EDIT: sauber getrennt vom +;; Ketten-Journal, keine Kollisionsgefahr mit dessen Marker-Schema +;; ("linienzug"/"linienzug2"/"standard"/"etage"). Wird auf JEDES seit +;; Glied-Start neu erzeugte Entity geschrieben, WAEHREND es noch frei in der +;; Zeichnung liegt (vor dem finalen -BLOCK-Sweep in vfl-block-erstellen) - +;; siehe vfl-segment-xdata-sichern. Rein additive Zusatzinformation: das +;; bestehende Ketten-Journal (SSG_VF_EDIT) bleibt unabhaengig davon die +;; primaere/vollstaendige Quelle, Segment-XDATA ist kein Ersatz dafuer. +;; Layout: [0]="linienzug-seg" (Marker), [1]=Glied-Index (1-basiert, String), +;; [2..]=Segment-Journal-String in 250-Byte-Chunks. +(defun vfl-journal-xdata-schreiben-seg (ent seg-idx seg-journal / chunks appentry) + (regapp "SSG_VF_EDIT_SEG") + (setq chunks (vfl-chunk-string (vfl-journal-list->string seg-journal) 250)) + (setq appentry + (cons "SSG_VF_EDIT_SEG" + (cons (cons 1000 "linienzug-seg") + (cons (cons 1000 (itoa seg-idx)) + (mapcar (function (lambda (c) (cons 1000 c))) chunks))))) + (entmod (append (entget ent) (list (list -3 appentry)))) + ent) +;; Rueckgabe: (seg-idx . segment-journal) oder nil (kein/unbekanntes Segment-XDATA). +(defun vfl-journal-xdata-lesen-seg (ent / xd app-data werte) + (setq xd (entget ent '("SSG_VF_EDIT_SEG"))) + (setq app-data (cdr (assoc -3 xd))) + (if app-data + (progn + (setq werte (mapcar 'cdr (cdr (car app-data)))) + (if (and werte (= (car werte) "linienzug-seg") (cadr werte)) + (cons (atoi (cadr werte)) (vfl-string->journal (apply 'strcat (cddr werte)))) + nil)) + nil)) + +;; Wird direkt nach dem Segment-Dispatch-cond in vf-linienzug-modus aufgerufen +;; (per vl-catch-all-apply abgesichert - ein Fehler hier darf den Hauptbau nie +;; abbrechen, rein additive Zusatz-XDATA). seg-lastEnt = Schnappschuss VOR +;; diesem Glied (vf-lastent-ohne-attribute, siehe Aufruf). wahl wird hier +;; nicht mehr gebraucht (das Label steckt schon im STEP-Eintrag des Journals +;; via vfl-journal-steplabel) - Parameter bleibt fuer eine spaetere dbgmsg- +;; Diagnose nuetzlich, daher weiterhin uebergeben. +;; Ermittelt Glied-Index + Journal-Teilsequenz selbst aus dem aktuellen +;; *vfl-journal* (zu diesem Zeitpunkt bereits um dieses Glied vollstaendig +;; ergaenzt) und schreibt sie auf JEDES seit seg-lastEnt neu erzeugte Entity +;; (entnext-Wanderung, gleiches Muster wie vfl-block-erstellen/ +;; vfl-modus-abbruch-sichern). +(defun vfl-segment-xdata-sichern (seg-lastEnt wahl / forward-journal seg-idx seg-journal e) + (setq forward-journal (reverse *vfl-journal*)) + (setq seg-idx (length (vfl-journal-glieder forward-journal))) + (if (> seg-idx 0) + (progn + (setq seg-journal (vfl-journal-slice forward-journal seg-idx)) + (setq e (if seg-lastEnt (entnext seg-lastEnt) (entnext))) + (while e + (vfl-journal-xdata-schreiben-seg e seg-idx seg-journal) + (setq e (entnext e)) + ) + ) + ) + (dbgmsg (strcat "SEGMENT-XDATA: Glied " (itoa seg-idx) " (" (if wahl wahl "?") ") gesichert")) + (princ)) + ;; --- Abbruch-Sicherung --- ;; Alle nach lastEnt erzeugten Entities werden NICHT geloescht, sondern ;; GENAUSO wie beim erfolgreichen Abschluss (vfl-block-erstellen) zu einem @@ -925,6 +1034,40 @@ (setq out (cons e out))))) (reverse out)) +;; Journal-Eintraege GENAU eines Glieds liefern: der (from-step-idx)-te STEP +;; (1-basiert, in Bau-Reihenfolge) bis ausschliesslich dem naechsten STEP. +;; Praeambel-Eintraege vor dem 1. STEP gehoeren zu keinem Glied und werden +;; hier nie zurueckgegeben (anders als vfl-journal-truncate, das sie immer +;; mitnimmt). Genutzt fuer die Segment-XDATA (vfl-segment-xdata-sichern) und +;; das Ersetzen eines einzelnen Glieds (vfl-journal-splice). +(defun vfl-journal-slice (forward-journal from-step-idx / seen out started done) + (setq seen 0 out '() started nil done nil) + (foreach e forward-journal + (if (not done) + (cond + ((and (= (car e) "STEP") started) (setq done t)) + ((= (car e) "STEP") + (setq seen (1+ seen)) + (if (= seen from-step-idx) (progn (setq started t) (setq out (cons e out))))) + (started (setq out (cons e out)))))) + (reverse out)) + +;; Journal-Eintraege des Glieds (seg-idx) durch (new-seg-journal) ersetzen - +;; alle anderen Glieder (davor UND danach) sowie die Praeambel bleiben +;; unveraendert. Gegenstueck zu vfl-journal-slice (welches genau dieses Glied +;; ISOLIERT liefert). Genutzt von der Einzelsegment-Bearbeitung (vfl-edit-glied). +(defun vfl-journal-splice (forward-journal seg-idx new-seg-journal / seen out) + (setq seen 0 out '()) + (foreach e forward-journal + (progn + (if (= (car e) "STEP") (setq seen (1+ seen))) + (cond + ((< seen seg-idx) (setq out (cons e out))) ; vor dem Ziel-Glied: unveraendert + ((> seen seg-idx) (setq out (cons e out))) ; nach dem Ziel-Glied: unveraendert + ((and (= seen seg-idx) (= (car e) "STEP")) ; Ziel-Glied: einmalig durch + (setq out (append (reverse new-seg-journal) out)))))) ; new-seg-journal ersetzen, + (reverse out)) ; alle uebrigen Eintraege verwerfen + ;; Internes (sprachneutrales) Glied-Token in lesbaren Text der AKTUELLEN Sprache ;; uebersetzen. Da im Journal nur das Token steht, folgt die Anzeige immer der ;; aktiven Sprache - ein in Deutsch aufgezeichnetes Journal zeigt in englischer @@ -1369,36 +1512,95 @@ (setq gekappt (float (fix ist-hoehe))) (if (>= gekappt ist-hoehe) (- gekappt 1.0) gekappt)) -;; Rueckgabe: (deltaL hz p2) oder nil bei Abbruch. p2 = der rohe gepickte -;; Punkt (fuer Diagnose/Nachrechnung nach dem AS-Element-Insert, siehe -;; vfl-projiziere-distanz). Foerderer-Maximallaenge 25 m: bei Ueberschreitung -;; wird die Eingabe abgelehnt und der Endpunkt erneut abgefragt. -(defun vfl-neue-linie-messen (p-akt hz-vorgabe / p2 rad ux uy deltaL hz-aktuell ergebnis fertig) +;; Punkt+Prompt-Eingabe fuer eine neue Linie journalfrei in (deltaL . hz) +;; uebersetzen: LIVE wird ganz normal ein Punkt gepickt (Gummiband), aber +;; NICHT der Punkt selbst journalisiert, sondern nur die daraus berechnete +;; Distanz (immer) und - NUR wenn hz-vorgabe nil war (freie Richtung, gilt +;; ausschliesslich fuer das allererste Segment der Kette) - zusaetzlich die +;; gesnappte Richtung. Ist hz-vorgabe bereits gesetzt (jedes Nicht-Start- +;; Segment), journalisiert diese Funktion NUR deltaL - die Richtung ist ja +;; ohnehin immer die des Vorgaengers, ein Journal-Eintrag dafuer waere +;; redundant. Rueckgabe: (deltaL . hz) oder nil bei Abbruch/leerer Eingabe. +(defun vfl-in-abstand (p-akt hz-vorgabe prompt / p2 rad ux uy deltaL hz-aktuell popped) + (if *vfl-replay-queue* + (progn + ;; Replay: IMMER nur deltaL aus der Queue lesen (nie einen Punkt). Bei + ;; freier Richtung (hz-vorgabe nil) steht direkt DANACH noch die + ;; gesnappte Richtung als zweiter Eintrag im Journal (siehe + ;; Live-Zweig unten) - Reihenfolge: deltaL, dann optional hz. + (setq popped (vfl-replay-pop)) + (if (null popped) + (setq deltaL nil) + (setq deltaL (car popped))) + (if (and deltaL (null hz-vorgabe)) + (progn + (setq popped (vfl-replay-pop)) + (setq hz-aktuell (if popped (car popped) 0.0))) + (setq hz-aktuell hz-vorgabe))) + (progn + ;; Live/Wizard: Pending-Queue zuerst pruefen (Konsistenz mit den + ;; anderen vfl-in-*-Wrappern/Sicherheitsnetz, siehe vfl-wizard-aktiv- + ;; Kommentar oben) - aktuell legt kein Gruppen-Dialog hier einen Punkt + ;; ab, dieser Zweig bleibt also praktisch immer leer. Sonst normal + ;; picken (Gummiband). Der Punkt lebt nur hier lokal, er wird nie + ;; journalisiert. + (setq popped (vflw-pending-pop)) + (setq p2 (if popped (car popped) (vfl-getpoint p-akt prompt))) + (if (null p2) + (setq deltaL nil) + (progn + (setq hz-aktuell (if hz-vorgabe hz-vorgabe (vfl-hz-snappen-absolut (vfl-planar-hz p-akt p2)))) + (setq rad (* (float hz-aktuell) (/ pi 180.0)) ux (cos rad) uy (sin rad)) + (setq deltaL (+ (* (- (car p2) (car p-akt)) ux) (* (- (cadr p2) (cadr p-akt)) uy))))))) + ;; Journalisieren fuer BEIDE Zweige (Replay UND Live) - wie alle anderen + ;; vfl-in-*-Wrapper (siehe vfl-in-point/-real/-int): ein beim Replay aus der + ;; alten Queue gelesener Wert MUSS ins neue *vfl-journal* uebernommen werden, + ;; sonst fehlt er beim erneuten Speichern (vfl-journal-xdata-schreiben nach + ;; einem Edit) - genau das fuehrte beim ZWEITEN Edit einer Kette zum + ;; deltaL-Desync (die replizierten DL/Richtungs-Eintraege waren im nach dem + ;; ersten Edit gespeicherten Journal verschwunden). Reihenfolge identisch zur + ;; Lese-Reihenfolge oben: erst DL, dann - nur beim ersten Segment + ;; (hz-vorgabe nil) - die gesnappte Richtung als REAL. + (vfl-journal-record (if deltaL "DL" "NIL") deltaL) + (if (and deltaL (null hz-vorgabe)) + (vfl-journal-record "REAL" hz-aktuell)) + (if deltaL (cons deltaL hz-aktuell) nil)) + +;; Rueckgabe: (deltaL hz) oder nil bei Abbruch. Foerderer-Maximallaenge 25 m: +;; bei Ueberschreitung wird die Eingabe abgelehnt und der Endpunkt erneut +;; abgefragt. +;; +;; WICHTIG (siehe vfl-in-abstand): journalisiert wird NUR deltaL (+ ggf. die +;; gesnappte Richtung beim allerersten Segment), niemals ein absoluter Punkt. +;; deltaL ist eine reine Distanz relativ zum AKTUELLEN Frame (p-akt) entlang +;; der (ggf. vom Vorgaenger geerbten) Fahrtrichtung - eine absolute +;; Weltkoordinate wuerde dagegen nur zur URSPRUENGLICHEN Frame-Position +;; passen. Wird nach einem Einzelsegment-Edit (vfl-edit-glied, z.B. GF-Bogen +;; Seite/Winkel aendern) die Kette AB einem anderen Frame neu verkettet, ist +;; eine gespeicherte Distanz+Richtung sofort und ohne jede Umrechnung wieder +;; korrekt - ein gespeicherter absoluter Punkt waere es nicht (siehe Bug: +;; Neuprojektion des alten Punkts gegen den neuen Frame ergab eine falsche, +;; teils negative Laenge und in der Folge einen Queue-Desync-Absturz). +;; Einzige Ausnahme im ganzen Modus 1: der Kettenstartpunkt (vf-linienzug- +;; modus, vfl-in-point auf den allerersten Klick) - er bleibt ein echter +;; absoluter Punkt, weil er den einzigen Anker der ganzen Kette markiert und +;; von keiner Bogen-Aenderung betroffen sein kann. +(defun vfl-neue-linie-messen (p-akt hz-vorgabe / erg deltaL hz-aktuell ergebnis fertig) (vfl-view-refresh) (setq fertig nil) (while (not fertig) - (setq p2 (vfl-in-point p-akt - (if hz-vorgabe - (ssg-text "vfl-prompt-endpunkt-fahrtrichtung") - (ssg-text "vfl-prompt-endpunkt-frei")))) - (if (null p2) + (setq erg (vfl-in-abstand p-akt hz-vorgabe + (if hz-vorgabe + (ssg-text "vfl-prompt-endpunkt-fahrtrichtung") + (ssg-text "vfl-prompt-endpunkt-frei")))) + (if (null erg) (setq ergebnis nil fertig t) (progn - ;; Freie Richtung (nur beim allerersten Segment der Kette, hz-vorgabe - ;; noch nil): auf das feste 30-Grad-Raster des Weltkoordinatensystems - ;; snappen - im System sind Fahrtrichtungen immer 30/60/90-Grad- - ;; Vielfache relativ zur Zeichnung, nie ein freier Zwischenwert. Bei - ;; einem Retry (zu lang) bleibt hz-vorgabe bewusst nil, damit die - ;; Richtung erneut frei gewaehlt werden kann. - (setq hz-aktuell (if hz-vorgabe hz-vorgabe (vfl-hz-snappen-absolut (vfl-planar-hz p-akt p2)))) - (setq rad (* (float hz-aktuell) (/ pi 180.0)) ux (cos rad) uy (sin rad)) - ;; Skalarprojektion des gewaehlten Vektors auf die (ggf. gesnappte) - ;; Fahrtrichtung - (setq deltaL (+ (* (- (car p2) (car p-akt)) ux) (* (- (cadr p2) (cadr p-akt)) uy))) + (setq deltaL (car erg) hz-aktuell (cdr erg)) (if (> deltaL 25000.0) (princ (ssg-textf "vfl-fehler-laenge-max" (list (rtos (/ deltaL 1000.0) 2 2)))) (progn - (setq ergebnis (list deltaL hz-aktuell p2)) + (setq ergebnis (list deltaL hz-aktuell)) (setq fertig t) ) ) @@ -2136,16 +2338,25 @@ ) ;; Kettenanfang-Baustein: falls as-vorhanden, AS-Element einfuegen und die -;; GF/VF-Restlaenge aus dem tatsaechlichen KS_AUS neu berechnen (siehe -;; vfl-projiziere-distanz). Falls NICHT as-vorhanden (Nutzer hat "Kein AS- -;; Element" gewaehlt), beginnt die Kette direkt am Startpunkt - deltaL bleibt -;; die gemessene Rohlaenge (kein Fussabdruck abzuziehen). Rueckgabe: (frame -;; deltaL). -(defun vfl-kettenanfang-baustein (p-aktuell hz-neu pick-punkt deltaL as-seite as-vorhanden / frame) +;; GF/VF-Restlaenge um den tatsaechlichen AS-Fussabdruck kuerzen. Falls NICHT +;; as-vorhanden (Nutzer hat "Kein AS-Element" gewaehlt), beginnt die Kette +;; direkt am Startpunkt - deltaL bleibt die gemessene Rohlaenge (kein +;; Fussabdruck abzuziehen). Rueckgabe: (frame deltaL). +;; +;; deltaL kommt als reine, bereits auf hz-neu projizierte Distanz vom +;; UNVERAENDERTEN p-aktuell herein (siehe vfl-in-abstand/vfl-neue-linie- +;; messen - dort wird NIE mehr ein absoluter Punkt gefuehrt). Der reale +;; AS-Austritt (car frame) liegt exakt auf derselben Achse hz-neu (das +;; AS-Element wird flach IN hz-neu eingefuegt, siehe vfl-insert-as-element) - +;; die noetige Restlaenge ist damit einfach die urspruengliche Distanz MINUS +;; die tatsaechliche (gemessene) AS-Fussabdrucklaenge, keine Punkt-Projektion +;; noetig (Ersatz fuer das fruehere vfl-projiziere-distanz auf pick-punkt). +(defun vfl-kettenanfang-baustein (p-aktuell hz-neu deltaL as-seite as-vorhanden / frame fussabdruck) (if as-vorhanden (progn (setq frame (vfl-insert-as-element "GF" p-aktuell hz-neu 0.0 as-seite)) - (setq deltaL (vfl-projiziere-distanz (car frame) pick-punkt hz-neu)) + (setq fussabdruck (vfl-planar-dist p-aktuell (car frame))) + (setq deltaL (- deltaL fussabdruck)) (princ (ssg-textf "vfl-info-as-eingefuegt" (list (rtos deltaL 2 1)))) ) (progn @@ -2407,8 +2618,8 @@ p-aktuell linie-mess hoehe-neu hoehe-bis deltaL deltaH richtung hz-neu entscheidung typ winkel L_GF L_VF vf-einheit-res frame letzter-typ fertig linie-ende-modus rad3 - anzahl-gf anzahl-vf vfl-nummer lastEnt - gf-max-winkel gf-ok kettenanfang pick-punkt + anzahl-gf anzahl-vf vfl-nummer lastEnt seg-lastEnt + gf-max-winkel gf-ok kettenanfang as-vorhanden erg old-error vfl-ins dbg-an hoehe-vorschlaege hoehe-ab hoehe-auf hoehe-fallback) (princ "\n\n=========================================") @@ -2427,6 +2638,15 @@ (progn (dbgf "vf-linienzug-modus") (dbgmsg "=== SESSION Modus 1 (Manuelle Eingabe) START ===") + ;; Diagnose: falls dieser Lauf ein Replay ist (Editieren/Fortsetzen, + ;; *vfl-replay-queue* gesetzt), die EINGEHENDE Replay-Queue als JSON + ;; ausgeben - VOR dem Neuaufbau, daher auch bei einem Absturz mitten im + ;; Replay sichtbar (anders als das XDATA-JOURNAL-JSON in + ;; vfl-journal-xdata-schreiben, das erst nach erfolgreichem Bau laeuft). + ;; So laesst sich ein Desync direkt an der Eingangs-Sequenz ablesen. + (if *vfl-replay-queue* + (dbgmsg (strcat "REPLAY-QUEUE-JSON " (vfl-journal->json *vfl-replay-queue*))) + (dbgmsg "LIVE-BAU (kein Replay)")) (dbgflush))) ;; Abhaengigkeit: die GF-Segmente/-Boegen nutzen Funktionen aus @@ -2547,6 +2767,11 @@ ;; nachgetragen (vfl-journal-steplabel), damit jedes Glied seine eigene ;; Menue-Auswahl + Segment-Eingaben vollstaendig umschliesst (fuer den ;; gliedweisen Ruecksprung beim Editieren). + ;; seg-lastEnt: Schnappschuss VOR diesem Glied, fuer die Segment-XDATA + ;; (vfl-segment-xdata-sichern, siehe Ende der cond unten) - dieselbe + ;; Hilfsfunktion wie beim Ketten-lastEnt (oben), damit ATTRIB/SEQEND- + ;; Ketten eines vorherigen INSERTs konsistent uebersprungen werden. + (setq seg-lastEnt (vf-lastent-ohne-attribute)) (vfl-journal-mark "?") (if frame (progn @@ -2588,6 +2813,7 @@ ;; Segmenttyp steht fest -> Glied-Label nachtragen (fuer die Edit-Liste). (vfl-journal-steplabel wahl) + (progn (cond ((= wahl "GF-Bogen") (setq frame (vfl-insert-gf-bogen frame)) @@ -2599,14 +2825,14 @@ (setq linie-mess (vfl-neue-linie-messen p-aktuell (if frame (car (frame->hz-winkel frame)) nil))) (if (null linie-mess) (progn (princ (ssg-text "vfl-abgebrochen")) (exit))) - (setq deltaL (car linie-mess) hz-neu (cadr linie-mess) pick-punkt (caddr linie-mess)) + (setq deltaL (car linie-mess) hz-neu (cadr linie-mess)) (setq kettenanfang (null frame)) ;; Kettenanfang: AS-Element (falls gewuenscht) SOFORT einfuegen, reale ;; Restlaenge aus dem tatsaechlichen KS_AUS nachrechnen (siehe ;; vfl-kettenanfang-baustein). (if kettenanfang (progn - (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu pick-punkt deltaL as-seite as-vorhanden)) + (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu deltaL as-seite as-vorhanden)) (setq frame (nth 0 erg) deltaL (nth 1 erg) p-aktuell (car frame)) ) ) @@ -2644,7 +2870,7 @@ (setq linie-mess (vfl-neue-linie-messen p-aktuell (if frame (car (frame->hz-winkel frame)) nil))) (if (null linie-mess) (progn (princ (ssg-text "vfl-abgebrochen")) (exit))) - (setq deltaL (car linie-mess) hz-neu (cadr linie-mess) pick-punkt (caddr linie-mess)) + (setq deltaL (car linie-mess) hz-neu (cadr linie-mess)) (setq kettenanfang (null frame)) (setq gf-max-winkel (float (ssg-cfg-or "vario" "gefaelle_winkel" 3))) (if (< deltaL 1.0) @@ -2661,7 +2887,7 @@ ;; Versatz). (if kettenanfang (progn - (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu pick-punkt deltaL as-seite as-vorhanden)) + (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu deltaL as-seite as-vorhanden)) (setq frame (nth 0 erg) deltaL (nth 1 erg) p-aktuell (car frame)) ) ) @@ -2790,14 +3016,14 @@ (setq linie-mess (vfl-neue-linie-messen p-aktuell (if frame (car (frame->hz-winkel frame)) nil))) (if (null linie-mess) (progn (princ (ssg-text "vfl-abgebrochen")) (exit))) - (setq deltaL (car linie-mess) hz-neu (cadr linie-mess) pick-punkt (caddr linie-mess)) + (setq deltaL (car linie-mess) hz-neu (cadr linie-mess)) (setq kettenanfang (null frame)) ;; Kettenanfang: AS-Element (falls gewuenscht) SOFORT einfuegen, reale ;; Restlaenge aus dem tatsaechlichen KS_AUS nachrechnen (siehe ;; vfl-kettenanfang-baustein). (if kettenanfang (progn - (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu pick-punkt deltaL as-seite as-vorhanden)) + (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu deltaL as-seite as-vorhanden)) (setq frame (nth 0 erg) deltaL (nth 1 erg) p-aktuell (car frame)) ) ) @@ -2861,7 +3087,7 @@ (setq linie-mess (vfl-neue-linie-messen p-aktuell (if frame (car (frame->hz-winkel frame)) nil))) (if (null linie-mess) (progn (princ (ssg-text "vfl-abgebrochen")) (exit))) - (setq deltaL (car linie-mess) hz-neu (cadr linie-mess) pick-punkt (caddr linie-mess)) + (setq deltaL (car linie-mess) hz-neu (cadr linie-mess)) (setq kettenanfang (null frame)) (if (< deltaL 1.0) (princ (ssg-text "vfl-fehler-linie-zu-kurz")) @@ -2873,7 +3099,7 @@ ;; vfl-kettenanfang-baustein). (if kettenanfang (progn - (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu pick-punkt deltaL as-seite as-vorhanden)) + (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu deltaL as-seite as-vorhanden)) (setq frame (nth 0 erg) deltaL (nth 1 erg) p-aktuell (car frame)) ) ) @@ -3026,6 +3252,13 @@ ) ) ) + ;; Segment-XDATA: alle seit seg-lastEnt neu erzeugten Entities dieses + ;; Glieds mit ihrer eigenen Journal-Teilsequenz markieren (rein additiv, + ;; siehe vfl-segment-xdata-sichern) - muss laufen, WAEHREND die Entities + ;; noch frei in der Zeichnung liegen (vor dem -BLOCK-Sweep in + ;; vfl-block-erstellen unten). + (vl-catch-all-apply 'vfl-segment-xdata-sichern (list seg-lastEnt wahl)) + ) ) (setq hoehe-bis (caddr (car frame))) @@ -3070,7 +3303,133 @@ ;; (vfl-edit-ent2) - Modus 2s Klassifizierungs-Schleife traegt keine ;; Glied-Marker, ein Sektions-Dialog wie bei Modus 1 ist dafuer (noch) nicht ;; vorgesehen. -(defun vfl-edit-ent (ent / xd marker journal glieder n i pos trunc) +;; ============================================================ +;; EINZELSEGMENT-BEARBEITUNG (ein Glied aendern, Rest behalten) +;; ============================================================ +;; Idee: das Ketten-Journal ist die vollstaendige, wiederabspielbare Bau- +;; Anleitung. Ein einzelnes Glied editieren = dessen Journal-Teilsequenz durch +;; eine neue ersetzen (vfl-journal-splice) und danach das GESAMTE ersetzte +;; Journal still abspielen (vfl-journal-replay-start + vf-linienzug-modus) - +;; exakt derselbe Mechanismus wie der Sektions-Ruecksprung, nur mit chirurgisch +;; ersetztem statt abgeschnittenem Journal. Die Glieder VOR dem geaenderten +;; spielen identisch wie zuvor ab (gleicher Frame), das geaenderte Glied mit +;; neuen Werten, die Glieder DANACH mit ihren ORIGINAL-Werten - aber ab dem +;; neuen Austritts-Frame des geaenderten Glieds neu verkettet. Das leistet die +;; bestehende Replay-Schleife von allein (jedes Glied baut relativ zum Frame +;; des Vorgaengers), ohne Zusatzlogik. +;; +;; Umfang dieser ersten Version: sauber editierbar ist der GF-Bogen (genau eine +;; Winkel- + eine Seiten-Entscheidung, ein eigenstaendiges Top-Level-Glied). +;; Andere Glieder (Linie-GF/-VF, Horizontal-VF, Linie-bis-Ende) enthalten +;; Punktwahl + Hoehen und teils VF-interne Vario-Kurven - fuer die ist der +;; Sektions-Ruecksprung ("rueck") der passende Weg. Sie werden hier mit einem +;; Hinweis abgewiesen (statt eine halbfertige In-Place-Bearbeitung anzubieten). + +;; Neue Journal-Teilsequenz fuer einen GF-Bogen aus den im Dialog gewaehlten +;; Werten bauen. Aufbau exakt wie vom Live-Bau erzeugt: STEP-Eintrag, dann +;; ("STR" . "1") fuer die "Naechstes Element waehlen"-Menueantwort (Option 1 = +;; GF-Bogen, siehe vf-linienzug-modus Hauptschleife - vfl-journal-mark setzt +;; den STEP-Checkpoint VOR dieser Menuefrage, vfl-journal-steplabel schreibt +;; danach nur das Label um, fuegt aber KEINEN neuen Eintrag ein; die +;; Menueantwort bleibt also als eigener Journal-Eintrag direkt nach dem STEP +;; stehen), dann ("INT" . winkel-idx) + ("STR" . seite-code) aus +;; vfl-insert-gf-bogen (vfl-menu-int Winkel, vfl-menu Seite). winkel-idx +;; 1/2/3 = 30/60/90, seite-code "1"=links, "2"=rechts. Ein GF-Bogen kann nie +;; das erste Kettenglied sein (am Kettenanfang bietet das Menue "GF-Bogen" +;; gar nicht erst an, siehe Hauptschleife) - die Menueantwort ist daher immer +;; aus dem 5er-Menue (frame vorhanden) und immer "1". Rueckgabe: forward-order +;; Journal-Teilsequenz. +(defun vfl-gf-bogen-slice-bauen (winkel-idx seite-code) + (list (cons "STEP" "GF-Bogen") + (cons "STR" "1") + (cons "INT" winkel-idx) + (cons "STR" seite-code))) + +;; Aktuelle (Winkel-Index, Seiten-Code) aus einer bestehenden GF-Bogen-Slice +;; lesen (fuer die Dialog-Vorbelegung). Die Slice traegt ZWEI STR-Eintraege +;; (die fuehrende "Naechstes Element waehlen"-Menueantwort, danach - NACH dem +;; INT-Winkel - der Seiten-Code) - nur der STR NACH dem INT ist der Seiten- +;; Code, daher explizit per Positions-Flag statt "letzter gesehener STR +;; gewinnt" (siehe vfl-gf-bogen-slice-bauen). Faellt bei unerwartetem Aufbau +;; auf die Live-Bau-Defaults zurueck (Winkel 90 = idx 3, Seite links = "1"). +(defun vfl-gf-bogen-slice-werte (slice / w s nach-int) + (setq w 3 s "1" nach-int nil) + (foreach e slice + (cond ((= (car e) "INT") (setq w (cdr e) nach-int t)) + ((and (= (car e) "STR") nach-int) (setq s (cdr e) nach-int nil)))) + (list w s)) + +;; Pre-fill-faehiger Winkel+Seite-Dialog fuer den GF-Bogen (nutzt das +;; bestehende vflw_winkel_seite-Tile aus dem Wizard-DCL, aber mit Vorbelegung +;; auf die aktuellen Werte - anders als vflw-gruppe-winkel-seite-impl, das +;; immer bei 0 startet und daher nicht wiederverwendet werden kann, ohne den +;; Live-Bau zu beruehren). Rueckgabe: (winkel-idx seite-code) oder nil bei +;; Abbruch. winkel-idx 1/2/3, seite-code "1"/"2". +(defun vfl-glied-gf-bogen-dialog (vor-winkel-idx vor-seite-code / + dat dcl-pfad ergebnis gwinkel gseite) + (setq dcl-pfad (strcat (getenv "DXFM_DCL") "/vf_linienzug_wizard.dcl")) + (setq dat (load_dialog dcl-pfad)) + (if (not (new_dialog "vflw_winkel_seite" dat)) + (progn (if (and dat (>= dat 0)) (unload_dialog dat)) + (alert (ssg-textf "vfl-edit-dialog-fehlt" (list dcl-pfad))) nil) + (progn + (set_tile "kopf" (ssg-text "vfl-gf-bogen-winkel-header")) + (start_list "winkel") + (add_list (ssg-text "vfl-winkel-30")) + (add_list (ssg-text "vfl-winkel-60")) + (add_list (ssg-text "vfl-winkel-90")) + (end_list) + (set_tile "winkel" (itoa (1- vor-winkel-idx))) ; idx 1/2/3 -> 0-basiert 0/1/2 + (start_list "seite") + (add_list (ssg-text "gf-seite-links")) + (add_list (ssg-text "gf-seite-rechts")) + (end_list) + (set_tile "seite" (if (= vor-seite-code "2") "1" "0")) + (action_tile "accept" + "(setq gwinkel (get_tile \"winkel\")) (setq gseite (get_tile \"seite\")) (done_dialog 1)") + (action_tile "cancel" "(done_dialog 0)") + (setq ergebnis (start_dialog)) + (unload_dialog dat) + (if (= ergebnis 1) + (list (1+ (atoi gwinkel)) ; 0-basiert -> idx 1/2/3 + (if (= gseite "1") "2" "1")) ; Liste 0=links/1=rechts -> code "1"/"2" + nil)))) + +;; Einzelnes Glied bearbeiten. glieder = Glied-Label-Liste (Bau-Reihenfolge). +;; journal = volles Ketten-Journal. Waehlt per Liste ein Glied, laesst dessen +;; Eigenschaften aendern (aktuell nur GF-Bogen), ersetzt die Teilsequenz und +;; baut die Kette komplett neu auf (stummer Voll-Replay des gespliceten +;; Journals). Bricht der Neuaufbau ab, wickelt der bestehende *error*-Handler +;; in vf-linienzug-modus den Zwischenstand - kein Sonderfall noetig. +(defun vfl-edit-glied (ent journal glieder / pos label alt-slice vorwerte + neuwerte neu-slice spliced) + (setq pos (vfl-dlg-position glieder)) + (if (null pos) + (progn (princ (ssg-text "vfl-edit-abgebrochen")) (exit))) + (setq label (nth (1- pos) glieder)) + (cond + ((= label "GF-Bogen") + (setq alt-slice (vfl-journal-slice journal pos)) + (setq vorwerte (vfl-gf-bogen-slice-werte alt-slice)) + (setq neuwerte (vfl-glied-gf-bogen-dialog (car vorwerte) (cadr vorwerte))) + (if (null neuwerte) + (progn (princ (ssg-text "vfl-edit-abgebrochen")) (exit))) + (setq neu-slice (vfl-gf-bogen-slice-bauen (car neuwerte) (cadr neuwerte))) + (setq spliced (vfl-journal-splice journal pos neu-slice)) + (entdel ent) + (princ (ssg-textf "vfl-glied-geaendert" (list (itoa pos)))) + ;; Voller stummer Replay des gespliceten Journals: die Queue beschreibt + ;; die Kette bis zum Ende, daher faellt vf-linienzug-modus nicht in den + ;; Live-Modus, sondern baut 1:1 mit dem geaenderten Glied fertig. + (vfl-journal-replay-start spliced) + (vf-linienzug-modus)) + (t + (alert (ssg-textf "vfl-glied-nicht-editierbar" + (list (vfl-glied-label-text label)))) + (princ (ssg-text "vfl-edit-abgebrochen")))) + (princ)) + +(defun vfl-edit-ent (ent / xd marker journal glieder n i pos trunc edit-modus) (setq xd (vfl-journal-xdata-lesen ent)) (if (null xd) (progn (alert (ssg-text "vfl-edit-kein-journal")) (exit))) @@ -3080,23 +3439,34 @@ (progn (setq glieder (vfl-journal-glieder journal)) (setq n (length glieder)) - (princ (ssg-textf "vfl-edit-kette-header" (list (itoa n)))) - (setq i 1) - (foreach g glieder - (princ (strcat "\n " (itoa i) ") " (vfl-glied-label-text g))) - (setq i (1+ i))) - (setq pos (vfl-dlg-position glieder)) - (if (null pos) - (progn (princ (ssg-text "vfl-edit-abgebrochen")) (exit))) - (setq trunc (vfl-journal-truncate journal pos)) - ;; Alten Block entfernen (wie Standard/Etage: entdel + kompletter Neuaufbau). - ;; Bricht der Neuaufbau selbst ab, wickelt vfl-modus-abbruch-sichern den - ;; Zwischenstand automatisch zu einem neuen Block - kein Sonderfall noetig. - (entdel ent) - (princ (ssg-textf "vfl-edit-abgespielt" (list (itoa pos) (itoa (- n pos))))) - ;; Behaltene Glieder abspielen, dann live weiterbauen. - (vfl-journal-replay-start trunc) - (vf-linienzug-modus))) + ;; NEU: zuerst Modus waehlen (Sektion zuruecksetzen ODER ein einzelnes + ;; Glied bearbeiten). Alte Bloecke ohne Segment-XDATA funktionieren in + ;; beiden Zweigen, da beide allein aus dem Ketten-Journal arbeiten. + (setq edit-modus (vfl-dlg-modus n)) + (cond + ((null edit-modus) + (princ (ssg-text "vfl-edit-abgebrochen"))) + ((= edit-modus "glied") + (vfl-edit-glied ent journal glieder)) + (t + ;; --- bestehender Ablauf: Sektion zuruecksetzen (unveraendert) --- + (princ (ssg-textf "vfl-edit-kette-header" (list (itoa n)))) + (setq i 1) + (foreach g glieder + (princ (strcat "\n " (itoa i) ") " (vfl-glied-label-text g))) + (setq i (1+ i))) + (setq pos (vfl-dlg-position glieder)) + (if (null pos) + (progn (princ (ssg-text "vfl-edit-abgebrochen")) (exit))) + (setq trunc (vfl-journal-truncate journal pos)) + ;; Alten Block entfernen (wie Standard/Etage: entdel + kompletter Neuaufbau). + ;; Bricht der Neuaufbau selbst ab, wickelt vfl-modus-abbruch-sichern den + ;; Zwischenstand automatisch zu einem neuen Block - kein Sonderfall noetig. + (entdel ent) + (princ (ssg-textf "vfl-edit-abgespielt" (list (itoa pos) (itoa (- n pos))))) + ;; Behaltene Glieder abspielen, dann live weiterbauen. + (vfl-journal-replay-start trunc) + (vf-linienzug-modus))))) (princ)) ;; Modus-2-Block per Doppelklick zuruecksetzen: voller Reset - die komplette @@ -3111,6 +3481,35 @@ (vf-linienzug-modus2) (princ)) +;; DCL-Dialog nach Doppelklick: Editier-Modus waehlen. +;; n = Anzahl Glieder (nur fuer die Kopfzeile). Vorbelegung "rueck" (das +;; bisherige Verhalten, geringste Ueberraschung). Rueckgabe: "rueck", "glied" +;; oder nil (Abbrechen/Escape). Bei fehlendem/kaputtem DCL faellt der Dialog +;; auf "rueck" zurueck (statt die Bearbeitung ganz zu blockieren) - so bleibt +;; der bestehende Editierpfad auch dann erreichbar. +(defun vfl-dlg-modus (n / dcl-pfad dat wahl ergebnis) + (setq dcl-pfad (strcat (getenv "DXFM_DCL") "/vfl_edit_modus.dcl")) + (setq dat (load_dialog dcl-pfad)) + (if (not (new_dialog "vfl_edit_modus" dat)) + (progn + (if dat (unload_dialog dat)) + (alert (ssg-textf "vfl-edit-dialog-fehlt" (list dcl-pfad))) + "rueck") ; Fallback: bisheriges Verhalten + (progn + ;; Nur der Kopftext wird zur Laufzeit gesetzt; die Optionslabels stehen + ;; statisch (deutsch) im DCL - siehe vfl_edit_modus.dcl. get_tile "modus" + ;; liefert den key des gewaehlten radio_button. Default "modus_rueck" ist + ;; im DCL per value="1" vorbelegt. + (set_tile "kopf" (ssg-textf "vfl-dlg-modus-kopf" (list (itoa n)))) + (action_tile "accept" "(setq wahl (get_tile \"modus\")) (done_dialog 1)") + (action_tile "cancel" "(done_dialog 0)") + (setq ergebnis (start_dialog)) + (unload_dialog dat) + (cond + ((/= ergebnis 1) nil) + ((= wahl "modus_glied") "glied") + (t "rueck"))))) ; modus_rueck (o. leer) = zuruecksetzen + ;; DCL-Dialog: Sektion waehlen, auf die die Kette zurueckgesetzt wird. ;; glieder = Liste der Glied-Labels (interne Tokens, vfl-journal-glieder), in ;; Bau-Reihenfolge. Vorbelegung auf den letzten Eintrag (voller Stand = reines diff --git a/dcl/vfl_edit.dcl b/dcl/vfl_edit.dcl index 9f497f4..1c085bc 100644 --- a/dcl/vfl_edit.dcl +++ b/dcl/vfl_edit.dcl @@ -12,12 +12,14 @@ vfl_edit : dialog { : text { key = "kopf"; label = ""; + width = 70; } : popup_list { key = "position"; label = "Zuruecksetzen zu Sektion:"; - width = 40; + edit_width = 60; + list_width = 60; } } diff --git a/dcl/vfl_edit_modus.dcl b/dcl/vfl_edit_modus.dcl new file mode 100644 index 0000000..0aa81cb --- /dev/null +++ b/dcl/vfl_edit_modus.dcl @@ -0,0 +1,45 @@ +// ============================================================ +// vfl_edit_modus.dcl - Linienzug-Kette (VF_n, Marker "linienzug") +// per Doppelklick bearbeiten: zuerst den Modus waehlen - +// key "modus_rueck" = auf eine Sektion zuruecksetzen und ab dort +// weiterbauen (bestehendes Verhalten, +// vfl-dlg-position/vfl-journal-truncate) +// key "modus_glied" = Eigenschaften EINES einzelnen Glieds aendern, +// Rest bleibt (vfl-edit-glied) +// Aufruf ueber vfl-edit-ent -> vfl-dlg-modus (Lisp/vf_linienzug.lsp). +// Labels stehen wie in allen DCL-Files statisch (deutsch) hier - NICHT per +// set_tile gefuellt (set_tile kann das label eines radio_button ohnehin nicht +// setzen, nur den Zustand). Nur der Kopftext "kopf" wird zur Laufzeit gesetzt. +// ============================================================ + +vfl_edit_modus : dialog { + label = "Linienzug editieren"; + + : column { + + : text { + key = "kopf"; + label = ""; + } + + : boxed_radio_column { + label = "Was moechten Sie tun?"; + key = "modus"; + + : radio_button { + key = "modus_rueck"; + label = "Auf eine Sektion zuruecksetzen und ab dort neu bauen"; + value = "1"; + } + + : radio_button { + key = "modus_glied"; + label = "Nur die Eigenschaften eines einzelnen Glieds aendern"; + } + + } + + } + + ok_cancel; +} diff --git a/lang/de_DE.json b/lang/de_DE.json index d78eb66..4a84beb 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -766,6 +766,12 @@ "vfl-edit-dialog-fehlt": "Dialog nicht gefunden: %1", "vfl-edit-abgebrochen": "\nEditieren abgebrochen - keine Aenderung.", "vfl-dlg-kopf-sektionen": "Sektionen: %1", + "vfl-dlg-modus-kopf": "Linienzug mit %1 Glied(ern) - was moechten Sie tun?", + "vfl-dlg-modus-rueck": "Auf eine Sektion zuruecksetzen und ab dort neu bauen", + "vfl-dlg-modus-glied": "Nur die Eigenschaften eines einzelnen Glieds aendern", + "vfl-glied-waehlen-kopf": "Welches Glied moechten Sie bearbeiten?", + "vfl-glied-geaendert": "\n>>> Glied %1 geaendert - Kette wird neu aufgebaut...", + "vfl-glied-nicht-editierbar": "Dieses Glied (%1) kann derzeit nicht einzeln bearbeitet werden.\nNur GF-Bogen-Glieder sind einzeln editierbar. Fuer alle anderen bitte den Modus 'Auf eine Sektion zuruecksetzen' verwenden.", "vfc-warnung-untermodule-nicht-geladen": "\n[vf_core] WARNUNG: DXFM_LISP nicht gesetzt - Untermodule konnten nicht geladen werden!", "vfc-linienzug-modus-header": "\n\nLinienzug-Modus waehlen:", "vfc-linienzug-modus-1": "\n 1 - Manuelle Eingabe (Punkte klicken)", diff --git a/lang/en_GB.json b/lang/en_GB.json index 261b96f..de5316e 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -766,6 +766,12 @@ "vfl-edit-dialog-fehlt": "Dialog not found: %1", "vfl-edit-abgebrochen": "\nEdit cancelled - no change.", "vfl-dlg-kopf-sektionen": "Sections: %1", + "vfl-dlg-modus-kopf": "Chain with %1 segment(s) - what would you like to do?", + "vfl-dlg-modus-rueck": "Roll back to a section and rebuild from there", + "vfl-dlg-modus-glied": "Only change the properties of a single segment", + "vfl-glied-waehlen-kopf": "Which segment would you like to edit?", + "vfl-glied-geaendert": "\n>>> Segment %1 changed - rebuilding chain...", + "vfl-glied-nicht-editierbar": "This segment (%1) cannot currently be edited individually.\nOnly GF arc segments support single-segment editing. For all others please use the 'Roll back to a section' mode.", "vfc-warnung-untermodule-nicht-geladen": "\n[vf_core] WARNING: DXFM_LISP not set - submodules could not be loaded!", "vfc-linienzug-modus-header": "\n\nSelect line-path mode:", "vfc-linienzug-modus-1": "\n 1 - Manual entry (click points)",