Linienzug: Abbruch wickelt Teil-Geometrie statt sie zu loeschen; Editieren per DCL-Dialog
Abbruch (ESC) im Linienzug-Baumodus loescht die bereits eingefuegte Geometrie nicht mehr, sondern wickelt sie wie ein fertiger Bau zu einem VF_n-Block und schreibt das volle Eingabe-Journal als XDATA drauf (vfl-modus-abbruch-sichern, ersetzt das bisherige Loesch-Rollback). Die Teil-Kette bleibt damit stehen und ist sofort per Doppelklick weiter editierbar/fortsetzbar - unabhaengig davon, ob der Abbruch beim frischen Bauen oder mitten in einem Editier-Neuaufbau passiert. Der bisherige Menuepunkt "Letzten Abbruch fortsetzen" (Session-Variable) entfaellt dadurch ersatzlos. vfl-edit-ent (Doppelklick-Editieren) fragt die Sektion, auf die zurueckgesetzt werden soll, jetzt per neuem DCL-Dialog ab (dcl/vfl_edit.dcl, vfl-dlg-position: Combobox 1..N + OK/Abbrechen) statt per Text-Prompt. Vorbelegung auf die letzte Sektion, damit Doppelklick + sofort OK einen abgebrochenen Bau nahtlos fortsetzt. Die *error*-Handler-Installation wandert vor den allerersten Prompt (vorher: nach Startpunkt/AS-Frage), damit ein ESC in diesem Fenster nicht mehr auf den ungeschuetzten vorherigen Handler faellt. Das Wickeln im Abbruch-Pfad ist per vl-catch-all-apply abgesichert, da vfl-block-erstellen intern einen BKS-Wechsel per (command "_.UCS" ...) macht. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+118
-84
@@ -132,7 +132,7 @@
|
||||
;; *vfl-journal* wird in UMGEKEHRTER Reihenfolge gehalten (neuestes zuerst, cons).
|
||||
|
||||
(defun vfl-journal-reset ()
|
||||
(setq *vfl-journal* '() *vfl-replay-queue* nil *vfl-edit-orig-ent* nil))
|
||||
(setq *vfl-journal* '() *vfl-replay-queue* nil))
|
||||
|
||||
;; Eintrag anhaengen (vorn, da Reverse-Reihenfolge).
|
||||
(defun vfl-journal-record (kind val)
|
||||
@@ -285,33 +285,44 @@
|
||||
(vfl-string->journal (apply 'strcat (cdr xd)))
|
||||
nil))
|
||||
|
||||
;; --- Abbruch-Rollback ---
|
||||
;; Alle nach lastEnt erzeugten Entities loeschen (Transaktions-Rollback der
|
||||
;; Teil-Geometrie) und das Journal der vollstaendig abgeschlossenen Glieder
|
||||
;; (*vfl-journal-commit*) fuer die Wiederaufnahme sichern. Aufgerufen aus dem
|
||||
;; *error*-Handler von vf-linienzug-modus.
|
||||
(defun vfl-modus-cleanup (lastEnt / e nxt cnt)
|
||||
;; --- Abbruch-Sicherung ---
|
||||
;; Alle nach lastEnt erzeugten Entities werden NICHT geloescht, sondern
|
||||
;; GENAUSO wie beim erfolgreichen Abschluss (vfl-block-erstellen) zu einem
|
||||
;; neuen VF_n-Block gewickelt, mit dem VOLLEN aktuellen Eingabe-Journal
|
||||
;; (inkl. des angefangenen, noch unfertigen letzten Gliedes) als XDATA. Die
|
||||
;; Geometrie bleibt in der Zeichnung stehen und ist sofort per Doppelklick
|
||||
;; weiter editierbar/fortsetzbar (vfl-edit-ent) - unabhaengig davon, ob es
|
||||
;; sich um einen frischen Bau oder einen Editier-Neuaufbau handelte (kein
|
||||
;; Sonderfall mehr noetig). Aufgerufen aus dem *error*-Handler von
|
||||
;; vf-linienzug-modus.
|
||||
(defun vfl-modus-abbruch-sichern (lastEnt vfl-nummer anzahl-gf anzahl-vf
|
||||
startpunkt frame as-seite es-seite /
|
||||
e cnt vfl-ins wickel-erg)
|
||||
(setq cnt 0 e (if lastEnt (entnext lastEnt) (entnext)))
|
||||
(while e
|
||||
(setq nxt (entnext e))
|
||||
(if (not (vl-catch-all-error-p (vl-catch-all-apply 'entdel (list e))))
|
||||
(setq cnt (1+ cnt)))
|
||||
(setq e nxt))
|
||||
(if (and (boundp '*vfl-edit-orig-ent*) *vfl-edit-orig-ent*)
|
||||
;; EDIT-Abbruch: den beim Edit vorab geloeschten Original-Block
|
||||
;; wiederherstellen (entdel ist im laufenden Befehl umkehrbar) und KEIN
|
||||
;; Resume anbieten - der Ausgangszustand ist ja komplett zurueck.
|
||||
(progn
|
||||
(vl-catch-all-apply 'entdel (list *vfl-edit-orig-ent*))
|
||||
(setq *vfl-edit-orig-ent* nil)
|
||||
(princ (ssg-textf "vfl-abbruch-edit" (list (itoa cnt)))))
|
||||
;; FRESH/RESUME-Abbruch: Journal der abgeschlossenen Glieder fuer die
|
||||
;; Wiederaufnahme sichern.
|
||||
(if *vfl-journal-commit*
|
||||
(progn
|
||||
(setq *vfl-journal-letzter-abbruch* (reverse *vfl-journal-commit*))
|
||||
(princ (ssg-textf "vfl-abbruch-resume" (list (itoa cnt)))))
|
||||
(princ (ssg-textf "vfl-abbruch-simpel" (list (itoa cnt))))))
|
||||
(while e (setq cnt (1+ cnt)) (setq e (entnext e)))
|
||||
(cond
|
||||
((or (= cnt 0) (null frame))
|
||||
(princ (ssg-text "vfl-abbruch-nichts-gebaut")))
|
||||
(t
|
||||
;; vfl-block-erstellen nutzt intern (command "_.UCS" ...) fuer den
|
||||
;; BKS-Wechsel (ssg-block-wrap-welt) - im *error*-Handler-Kontext
|
||||
;; riskanter als eine einfache Loesch-Schleife, daher abgesichert.
|
||||
(setq wickel-erg
|
||||
(vl-catch-all-apply
|
||||
(function (lambda ()
|
||||
(setq vfl-ins
|
||||
(vfl-block-erstellen vfl-nummer anzahl-gf anzahl-vf
|
||||
(caddr startpunkt) (caddr (car frame))
|
||||
(vfl-planar-dist startpunkt (car frame))
|
||||
as-seite es-seite startpunkt lastEnt))
|
||||
(if vfl-ins (vfl-journal-xdata-schreiben vfl-ins))))
|
||||
nil))
|
||||
(if (vl-catch-all-error-p wickel-erg)
|
||||
(princ (ssg-textf "vfl-abbruch-wickeln-fehler"
|
||||
(list (vl-catch-all-error-message wickel-erg))))
|
||||
(princ (ssg-textf "vfl-abbruch-gesichert" (list (itoa cnt)))))
|
||||
)
|
||||
)
|
||||
(princ))
|
||||
|
||||
;; Replay-Modus scharf schalten: die uebergebene (Vorwaerts-)Journalliste wird
|
||||
@@ -1495,6 +1506,43 @@
|
||||
|
||||
(if (or (not *lib-initialized*) (null bogen-auf)) (init-bibliothek))
|
||||
|
||||
;; --- Abbruch-Sicherung scharf schalten (VOR dem ersten Prompt!) ---
|
||||
;; Ab hier kann jederzeit Geometrie entstehen. Ein *error*-Handler faengt
|
||||
;; jeden Abbruch (ESC / (exit) / Laufzeitfehler) ab und WICKELT die bereits
|
||||
;; eingefuegte Teil-Geometrie (alles nach lastEnt) zu einem VF_n-Block mit
|
||||
;; dem vollen aktuellen Eingabe-Journal als XDATA (vfl-modus-abbruch-sichern)
|
||||
;; - die Geometrie bleibt stehen und ist per Doppelklick sofort weiter
|
||||
;; editierbar/fortsetzbar (kein Rollback mehr, kein separater
|
||||
;; "Fortsetzen"-Mechanismus noetig).
|
||||
;; Die Installation MUSS vor dem allerersten vfl-in-*-Aufruf erfolgen: ein
|
||||
;; echtes ESC (nicht ein leeres Enter) loest bei JEDEM get*-Aufruf sofort
|
||||
;; *error* aus (nicht nil) - ohne den Handler wuerde ein ESC in diesem
|
||||
;; Fenster auf den vorherigen Handler zurueckfallen (im Editier-Pfad: der
|
||||
;; ssg-start-Handler ohne Wickeln - der bereits geloeschte Original-Block
|
||||
;; waere dann ersatzlos weg). lastEnt/old-error/vfl-nummer/anzahl-gf/
|
||||
;; anzahl-vf/startpunkt/frame/as-seite/es-seite sind zur Aufrufzeit
|
||||
;; dynamisch gebunden und daher im Handler-Lambda sichtbar (AutoLISP
|
||||
;; dynamic scoping, gilt fuer die gesamte Laufzeit dieses Aufrufs, auch
|
||||
;; tief verschachtelt z.B. in vfl-vf-einheit).
|
||||
(setq vfl-nummer (vf-next-number))
|
||||
(setq lastEnt (vf-lastent-ohne-attribute))
|
||||
(setq anzahl-gf 0 anzahl-vf 0 frame nil)
|
||||
(setq old-error *error*)
|
||||
;; Abbruch-Handler: zuerst *error* zuruecksetzen (kein rekursiver
|
||||
;; Wiedereintritt bei einem Fehler waehrend des Wickelns), dann wickeln.
|
||||
;; Laeuft der Aufruf innerhalb einer ssg-start-Sitzung (Editier-Pfad via
|
||||
;; c:VARIOFOERDERER_EDIT -> vfl-edit-ent), wird diese mit ssg-end sauber
|
||||
;; geschlossen (Undo-Gruppe, gesicherte Systemvariablen, *error* aus dem
|
||||
;; Sitzungs-Frame) - sonst bliebe die von ssg-start geoeffnete Undo-Gruppe
|
||||
;; offen.
|
||||
(setq *error*
|
||||
(function (lambda (msg)
|
||||
(setq *error* old-error)
|
||||
(vfl-modus-abbruch-sichern lastEnt vfl-nummer anzahl-gf anzahl-vf
|
||||
startpunkt frame as-seite es-seite)
|
||||
(if (and (boundp '*ssg-start-stack*) *ssg-start-stack*) (ssg-end))
|
||||
(princ))))
|
||||
|
||||
(setq startpunkt (vfl-in-point nil (ssg-text "vfl-prompt-startpunkt-kette")))
|
||||
(if (null startpunkt) (progn (princ (ssg-text "vfl-abgebrochen")) (exit)))
|
||||
;; Hoehe (Z) des Startpunkts abfragen und in die Z-Koordinate uebernehmen.
|
||||
@@ -1524,29 +1572,6 @@
|
||||
;; ES-Seite wird erst am Kettenende abgefragt (siehe vfl-frage-es-seite),
|
||||
;; da das ES-Element erst dort eingefuegt wird.
|
||||
|
||||
(setq vfl-nummer (vf-next-number))
|
||||
(setq lastEnt (vf-lastent-ohne-attribute))
|
||||
;; --- Abbruch-Rollback + Wiederaufnahme scharf schalten ---
|
||||
;; Ab hier wird Geometrie gebaut. Ein *error*-Handler faengt jeden Abbruch
|
||||
;; (ESC / (exit) / Laufzeitfehler) ab, entfernt die bereits eingefuegte
|
||||
;; Teil-Geometrie (alles nach lastEnt, siehe vfl-modus-cleanup) und sichert
|
||||
;; das Journal der bis dahin VOLLSTAENDIG abgeschlossenen Glieder
|
||||
;; (*vfl-journal-commit*) fuer die Wiederaufnahme. lastEnt/old-error sind zur
|
||||
;; Aufrufzeit dynamisch gebunden und daher im Handler sichtbar.
|
||||
(setq *vfl-journal-commit* nil)
|
||||
(setq old-error *error*)
|
||||
;; Abbruch-Handler: zuerst *error* zuruecksetzen (kein rekursiver Wiedereintritt
|
||||
;; bei einem Cleanup-Fehler), dann Teil-Geometrie zuruecknehmen. Laeuft der
|
||||
;; Aufruf innerhalb einer ssg-start-Sitzung (Edit-Pfad via c:VARIOFOERDERER_EDIT
|
||||
;; -> vfl-edit-ent), wird diese mit ssg-end sauber geschlossen (Undo-Gruppe,
|
||||
;; gesicherte Systemvariablen, *error* aus dem Sitzungs-Frame) - sonst bliebe
|
||||
;; die von ssg-start geoeffnete Undo-Gruppe offen.
|
||||
(setq *error*
|
||||
(function (lambda (msg)
|
||||
(setq *error* old-error)
|
||||
(vfl-modus-cleanup lastEnt)
|
||||
(if (and (boundp '*ssg-start-stack*) *ssg-start-stack*) (ssg-end))
|
||||
(princ))))
|
||||
(setq p-aktuell startpunkt)
|
||||
(setq letzter-typ nil fertig nil frame nil)
|
||||
(setq anzahl-gf 0 anzahl-vf 0)
|
||||
@@ -1568,11 +1593,6 @@
|
||||
;; nutzt weiterhin vfl-segment-entscheidung).
|
||||
(princ (ssg-text "vfl-naechstes-element-header"))
|
||||
(setq linie-ende-modus nil)
|
||||
;; Commit-Schnappschuss: Journalstand NACH dem letzten vollstaendig
|
||||
;; abgeschlossenen Glied (vor dem Marker der neuen, noch offenen Iteration).
|
||||
;; Bei Abbruch wird genau dieser Stand als Wiederaufnahme-Journal gesichert
|
||||
;; (das angefangene Glied faellt weg).
|
||||
(setq *vfl-journal-commit* *vfl-journal*)
|
||||
;; Glied-Checkpoint am Iterationskopf setzen; Label wird nach der Auswahl
|
||||
;; nachgetragen (vfl-journal-steplabel), damit jedes Glied seine eigene
|
||||
;; Menue-Auswahl + Segment-Eingaben vollstaendig umschliesst (fuer den
|
||||
@@ -1930,12 +1950,8 @@
|
||||
;; Eingabe-Journal am fertigen Block persistieren (Marker "linienzug" +
|
||||
;; Chunks) -> spaeter per Doppelklick editierbar (vfl-edit-ent).
|
||||
(if vfl-ins (vfl-journal-xdata-schreiben vfl-ins))
|
||||
;; Erfolgreicher Abschluss: *error* zuruecksetzen, evtl. offenes Abbruch-
|
||||
;; Journal verwerfen (die Kette ist fertiggestellt), Editier-Marker loeschen
|
||||
;; (der Original-Block bleibt im Edit-Fall geloescht - der Neuaufbau ersetzt ihn).
|
||||
;; Erfolgreicher Abschluss: *error* zuruecksetzen.
|
||||
(setq *error* old-error)
|
||||
(setq *vfl-journal-letzter-abbruch* nil)
|
||||
(setq *vfl-edit-orig-ent* nil)
|
||||
|
||||
(princ "\n\n=========================================")
|
||||
(princ (ssg-text "vfl-kette-eingefuegt"))
|
||||
@@ -1947,11 +1963,14 @@
|
||||
;; EDITIEREN: gliedweise zuruecknehmen + Neuaufbau per Replay
|
||||
;; ============================================================
|
||||
;; Aufgerufen aus c:VARIOFOERDERER_EDIT (Doppelklick auf VF_n mit XDATA-Marker
|
||||
;; "linienzug"). Liest das Eingabe-Journal vom Block, listet die Glieder, laesst
|
||||
;; k Glieder vom Ende zuruecknehmen, loescht den alten Block und baut die Kette
|
||||
;; neu: die behaltenen Glieder werden stumm abgespielt, danach laeuft die
|
||||
;; Eingabe interaktiv fuer die geaenderten/neuen Glieder weiter.
|
||||
(defun vfl-edit-ent (ent / journal glieder n i k trunc)
|
||||
;; "linienzug", egal ob fertiggestellt oder durch einen Abbruch gewickelt).
|
||||
;; Liest das Eingabe-Journal vom Block, listet die Glieder, laesst per
|
||||
;; DCL-Dialog (vfl-dlg-position) eine Sektion waehlen, auf die zurueckgesetzt
|
||||
;; wird, loescht den alten Block und baut die Kette neu: die behaltenen
|
||||
;; Glieder werden stumm abgespielt, danach laeuft die Eingabe interaktiv fuer
|
||||
;; die geaenderten/neuen Glieder weiter. Vorbelegung im Dialog = voller Stand
|
||||
;; -> Doppelklick + sofort OK setzt einen abgebrochenen Bau nahtlos fort.
|
||||
(defun vfl-edit-ent (ent / journal glieder n i pos trunc)
|
||||
(setq journal (vfl-journal-xdata-lesen ent))
|
||||
(if (null journal)
|
||||
(progn (alert (ssg-text "vfl-edit-kein-journal")) (exit)))
|
||||
@@ -1962,33 +1981,48 @@
|
||||
(foreach g glieder
|
||||
(princ (strcat "\n " (itoa i) ") " (vfl-glied-label-text g)))
|
||||
(setq i (1+ i)))
|
||||
(setq k (getint (ssg-textf "vfl-edit-wieviele" (list (itoa n)))))
|
||||
(if (or (null k) (< k 0)) (setq k 0))
|
||||
(if (> k n) (setq k n))
|
||||
(setq trunc (vfl-journal-truncate journal (- n k)))
|
||||
(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).
|
||||
;; *vfl-edit-orig-ent* merken, damit ein Abbruch waehrend des Neuaufbaus den
|
||||
;; Original-Block wiederherstellen kann (vfl-modus-cleanup).
|
||||
(setq *vfl-edit-orig-ent* ent)
|
||||
;; 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 (- n k)) (itoa k))))
|
||||
(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))
|
||||
|
||||
;; Wiederaufnahme des zuletzt abgebrochenen Linienzugs: das beim Abbruch
|
||||
;; gesicherte Journal abspielen und danach interaktiv weiterbauen.
|
||||
(defun vfl-modus-fortsetzen ( / )
|
||||
(if (and (boundp '*vfl-journal-letzter-abbruch*) *vfl-journal-letzter-abbruch*)
|
||||
;; 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
|
||||
;; Fortsetzen ohne Kuerzung). Rueckgabe: gewaehlte Position (1-basiert) oder
|
||||
;; nil bei Abbrechen/Escape.
|
||||
(defun vfl-dlg-position (glieder / n dcl-pfad dat idx ergebnis i)
|
||||
(setq n (length glieder))
|
||||
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/vfl_edit.dcl"))
|
||||
(setq dat (load_dialog dcl-pfad))
|
||||
(if (not (new_dialog "vfl_edit" dat))
|
||||
(progn (alert (ssg-textf "vfl-edit-dialog-fehlt" (list dcl-pfad))) nil)
|
||||
(progn
|
||||
(princ (ssg-text "vfl-fortsetzen-start"))
|
||||
(setq *vfl-edit-orig-ent* nil) ; Wiederaufnahme ist kein Edit -> kein Original restaurieren
|
||||
(vfl-journal-replay-start *vfl-journal-letzter-abbruch*)
|
||||
(vf-linienzug-modus))
|
||||
(progn
|
||||
(princ (ssg-text "vfl-fortsetzen-keiner"))
|
||||
(princ))))
|
||||
(set_tile "kopf" (ssg-textf "vfl-dlg-kopf-sektionen" (list (itoa n))))
|
||||
(start_list "position")
|
||||
(setq i 1)
|
||||
(foreach g glieder
|
||||
(add_list (strcat (itoa i) " - " (vfl-glied-label-text g)))
|
||||
(setq i (1+ i)))
|
||||
(end_list)
|
||||
(set_tile "position" (itoa (1- n))) ; letzter Eintrag vorbelegt (0-basierter Index)
|
||||
(action_tile "accept" "(setq idx (atoi (get_tile \"position\"))) (done_dialog 1)")
|
||||
(action_tile "cancel" "(done_dialog 0)")
|
||||
(setq ergebnis (start_dialog))
|
||||
(unload_dialog dat)
|
||||
(if (= ergebnis 1) (1+ idx) nil)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; ============================================================
|
||||
;; DIAGNOSE: Blockstruktur (KS_EIN/KS_AUS) untersuchen
|
||||
|
||||
Reference in New Issue
Block a user