[ADD] Block- und Text-Werkzeuge aus Walz (ACADSST) uebernommen

Neue Module ssg_blocktools.lsp (SSG_BLOCK_COUNT, SSG_BLOCK_DELETE,
SSG_ATTR_ERSETZEN) und ssg_texttools.lsp (SSG_TEXT_ERSETZEN,
SSG_TEXT_PARALLEL, SSG_TEXT_HOEHE, SSG_TEXT_STIL) sowie der generische
Eingabe-Wrapper ssg_input.lsp, dazu Menue-/Lade-Integration,
zweisprachige Texte und Unit-Tests fuer die reinen Kerne.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 11:40:11 +02:00
parent 2f9cb7eaed
commit fcb4444ee1
13 changed files with 8260 additions and 11 deletions
+4
View File
File diff suppressed because one or more lines are too long
+57
View File
@@ -323,6 +323,63 @@ Benutzerfreundliche BricsCAD-Befehle für Layer-Operationen. Alle Befehle sicher
---
### `ssg_input.lsp` – Generische Eingabe-Wrapper
Abfragen mit Vorgabewert (`<..>` im Prompt, Enter = Vorgabe). Steht neben den VF-spezifischen `vfl-in-*` (`vf_linienzug.lsp`); diese bleiben unveraendert. Kein Journal, aber ein optionaler Hook. ESC bricht wie ueblich ueber `*error*` ab.
| Funktion | Beschreibung |
| --- | --- |
| `ssg-in-real text default` | Reelle Zahl (`getreal`), Vorgabe ohne ueberfluessige Nullen angezeigt |
| `ssg-in-int text default` | Ganzzahl (`getint`) |
| `ssg-in-string text default` | String mit Leerzeichen; Enter ohne Eingabe liefert die Vorgabe (ohne Vorgabe `nil`) |
| `ssg-in-point text default base` | Punkt, `base` = Gummiband-Basispunkt oder `nil` |
| `ssg-in-dist text default base` | Abstand (`getdist`) |
| `ssg-in-keyword text schluessel default` | Schluesselwort im `initget`-Format, z.B. `"Alle Auswahl"` |
| `ssg-in-yesno text default` | Ja/Nein, **T = Ja**; `default` T = Enter bedeutet Ja. Woerter aus `ssg-text "in-yesno-keys"` |
| `ssg-in-default wert default`, `ssg-in-fmt-real`, `ssg-in-fmt-pt`, `ssg-in-prompt`, `ssg-in-first-word`, `ssg-in-second-word` | Reine Hilfsfunktionen (in `tests/test_unit.lsp` getestet) |
Hook (z.B. fuer ein Eingabe-Journal): `(setq *ssg-in-hook* 'meine-funktion)` mit `(defun meine-funktion (art prompt wert) ...)`; `art` ist `"REAL"`, `"INT"`, `"STRING"`, `"POINT"`, `"DIST"`, `"KEYWORD"` oder `"YESNO"`. Ein Hook, der einen Fehler wirft, wird abgeschaltet.
---
### `ssg_blocktools.lsp` – Block-Werkzeuge
Ursprung: ACADSST `TOOLS.LSP` (`BLKANZAHL`, `BLKENTF`), `DINGEN2` (`g-bli`), `ssg.lsp` (`suchen-aendern`). Arbeitet im **aktuellen Layout-Reiter**. Blocknamen werden ueber den wirksamen Namen verglichen (dynamische Bloecke); Muster mit `wcmatch` (`*`, `?`, `#`, ohne Gross-/Kleinschreibung).
| Befehl | Beschreibung |
| --- | --- |
| `SSG_BLOCK_COUNT` | Block anklicken, `Name` fuer ein Muster, oder Enter fuer eine Statistik aller Bloecke |
| `SSG_BLOCK_DELETE` | Alle Einfuegungen eines Blocks/Musters loeschen; Rueckfrage (Vorgabe Nein), Einfuegungen auf gesperrten Layern bleiben stehen; eine Undo-Gruppe |
| `SSG_ATTR_ERSETZEN` | Attributwerte suchen/ersetzen: Bereich (Alle mit Blockname-Muster / Auswahl), Tag-Muster, Suchtext, Ersatz, Modus Teil (Teilstring) oder Gesamt (ganzer Wert). Zeigt vorab die Anzahl und fragt nach |
| Funktion | Beschreibung |
| --- | --- |
| `ssg-bt-inserts muster` | Entity-Liste aller Einfuegungen im Layout (optional nach Muster) |
| `ssg-bt-statistik muster` | `((NAME . ANZAHL) ...)` alphabetisch |
| `ssg-bt-attr-ersetzen-ent ent tag suche ersatz teil-p probe-p` | Attribute EINER Einfuegung ersetzen bzw. nur zaehlen (`probe-p`); Rueckgabe Anzahl |
| `ssg-bt-attr-ersetzen-liste ents tag suche ersatz teil-p probe-p` | Dasselbe fuer eine Entity-Liste |
| `ssg-bt-wert-neu wert suche ersatz teil-p` | Reiner Kern: neuer Wert oder `nil` (unveraendert); beachtet Gross-/Kleinschreibung |
| `ssg-bt-name-passt-p`, `ssg-bt-zaehle-namen`, `ssg-bt-muster-escape` | Reine Hilfsfunktionen (getestet) |
---
### `ssg_texttools.lsp` – Text-Werkzeuge
Ursprung: ACADSST `CHGTEXT.LSP`, `PARTEXT.LSP`, `ALTHOEHE.LSP`, `ALTSTIL.LSP`. Laden **nach** `ssg_blocktools` (nutzt `ssg-bt-wert-neu` und `ssg-bt-attr-ersetzen-liste`). Arbeitet in der XY-Ebene des Welt-KS.
| Befehl | Beschreibung |
| --- | --- |
| `SSG_TEXT_ERSETZEN` | Suchen/Ersetzen in TEXT, MTEXT **und** Block-Attributen; Bereich Alle (Layout) oder Auswahl; Vorschau mit Anzahl, Rueckfrage |
| `SSG_TEXT_PARALLEL` | Linie/Polylinie/Bogen anklicken, Text wird parallel (lesbar, nie auf dem Kopf) mit Abstand gesetzt; Hoehe, Abstand und letzter Text werden fuer die Sitzung gemerkt; Enter beendet |
| `SSG_TEXT_HOEHE` | Texthoehe gewaehlter TEXT/MTEXT aendern |
| `SSG_TEXT_STIL` | Textstil gewaehlter TEXT/MTEXT aendern (Stil muss existieren) |
Reine Kerne (getestet): `ssg-tt-lesbarer-winkel` (Winkel 90 Grad bis 270 Grad um 180 Grad drehen, Ergebnis in [0, 2 pi)), `ssg-tt-versetzt`.
Nicht uebernommen aus Walz: `Export`/`Import` von Texten (besser per Python/ezdxf), `KREISTXT`, `TXTBOXED`, `CHTEXT`/`ASCTEXT`/`PTEXT` (Autodesk 1990, durch BricsCAD-Standard ersetzt).
---
### `ssg_load.lsp` – Laderoutine
Lädt alle Module in der richtigen Reihenfolge. Ermittelt den Pfad automatisch über `findfile`. Ruft direkt nach `ssg_core.lsp` die Funktion `ssg-load-config` auf, damit die JSON-Konfiguration für alle nachfolgenden Module verfügbar ist.
+311
View File
@@ -0,0 +1,311 @@
;; ============================================================
;; SSG_BLOCKTOOLS.LSP - Block-Werkzeuge fuer die aktuelle Zeichnung
;;
;; Ursprung: ACADSST/MENU/TOOLS.LSP (BLKANZAHL, BLKENTF), DINGEN2
;; (g-bli) und ssg.lsp (suchen-aendern) - neu geschrieben im ssg-Stil
;; (Undo-Gruppe, i18n, Ja/Nein-Rueckfrage, keine Globals).
;;
;; Befehle:
;; SSG_BLOCK_COUNT Einfuegungen zaehlen (ein Block, Namensmuster
;; oder Statistik aller Bloecke)
;; SSG_BLOCK_DELETE Alle Einfuegungen eines Blocks/Namensmusters
;; loeschen (mit Rueckfrage)
;; SSG_ATTR_ERSETZEN Attributwerte zeichnungsweit oder in einer
;; Auswahl suchen und ersetzen (mit Vorschau)
;;
;; Blocknamen werden ueber den WIRKSAMEN Namen verglichen (dynamische
;; Bloecke: EffectiveName statt "*U12"). Muster arbeiten mit wcmatch
;; (Platzhalter * ? #, ohne Beachtung der Gross-/Kleinschreibung).
;; Es wird nur der aktuelle Layout-Reiter (Modell ODER Papierbereich)
;; durchsucht.
;;
;; Setzt ssg_core.lsp, ssg_lang.lsp und ssg_input.lsp voraus.
;; ============================================================
(vl-load-com)
;; ------------------------------------------------------------
;; REINE HILFSFUNKTIONEN (in test_unit getestet)
;; ------------------------------------------------------------
;; T, wenn name auf das wcmatch-Muster passt (ohne Gross-/Kleinschreibung).
;; muster nil oder "" -> alle Namen passen.
(defun ssg-bt-name-passt-p (name muster)
(if (or (null muster) (= muster ""))
T
(if (wcmatch (strcase name) (strcase muster)) T nil)
)
)
;; Liste von Namen -> Alist ((NAME . ANZAHL) ...), alphabetisch sortiert
;; (ohne Beachtung der Gross-/Kleinschreibung).
(defun ssg-bt-zaehle-namen (namen / alist eintrag)
(foreach name namen
(setq eintrag (assoc name alist))
(if eintrag
(setq alist (subst (cons name (1+ (cdr eintrag))) eintrag alist))
(setq alist (cons (cons name 1) alist))
)
)
(vl-sort alist '(lambda (a b) (< (strcase (car a)) (strcase (car b)))))
)
;; Sonderzeichen eines Blocknamens fuer wcmatch maskieren (Backquote), damit
;; ein per Pick gewaehlter Name nur sich selbst trifft.
(defun ssg-bt-muster-escape (name / res i c)
(setq res "" i 1)
(while (<= i (strlen name))
(setq c (substr name i 1))
(if (vl-string-search c "#@.*?~[],`")
(setq res (strcat res "`"))
)
(setq res (strcat res c)
i (1+ i))
)
res
)
;; Muster ohne Maskier-Backquotes (fuer Meldungen)
(defun ssg-bt-muster-anzeige (muster)
(ssg-str-replace-all "" "`" muster)
)
;; Neuer Attributwert oder nil, wenn der Wert unveraendert bleibt.
;; teil-p = T : suche wird als Teilstring ueberall ersetzt
;; teil-p = nil: nur ersetzen, wenn der GESAMTE Wert gleich suche ist
;; Leere suche aendert nichts. Gross-/Kleinschreibung wird beachtet.
(defun ssg-bt-wert-neu (wert suche ersatz teil-p)
(cond
((or (null suche) (= suche "") (null wert)) nil)
(teil-p
(if (vl-string-search suche wert)
(ssg-str-replace-all ersatz suche wert)
nil
)
)
((= wert suche) ersatz)
(t nil)
)
)
;; ------------------------------------------------------------
;; ZEICHNUNGSZUGRIFF
;; ------------------------------------------------------------
;; Wirksamer Blockname einer Einfuegung (dynamische Bloecke beachten)
(defun ssg-bt-effname (ent / res)
(setq res (vl-catch-all-apply 'vla-get-effectivename
(list (vlax-ename->vla-object ent))))
(if (vl-catch-all-error-p res)
(cdr (assoc 2 (entget ent)))
res
)
)
;; T, wenn der Layer der Entity gesperrt ist
(defun ssg-bt-layer-gesperrt-p (ent / lay)
(setq lay (tblsearch "LAYER" (cdr (assoc 8 (entget ent)))))
(and lay (= 4 (logand 4 (cdr (assoc 70 lay)))))
)
;; Alle Einfuegungen im aktuellen Layout, optional gefiltert nach Namensmuster.
;; Rueckgabe: Liste von Entity-Namen (kann leer sein).
(defun ssg-bt-inserts (muster / ss i ent res)
(setq ss (ssget "_X" (list '(0 . "INSERT") (cons 410 (getvar "CTAB")))))
(if ss
(progn
(setq i 0)
(while (setq ent (ssname ss i))
(if (ssg-bt-name-passt-p (ssg-bt-effname ent) muster)
(setq res (cons ent res))
)
(setq i (1+ i))
)
)
)
(reverse res)
)
;; Statistik: ((NAME . ANZAHL) ...) fuer alle Einfuegungen passend zum Muster
(defun ssg-bt-statistik (muster)
(ssg-bt-zaehle-namen (mapcar 'ssg-bt-effname (ssg-bt-inserts muster)))
)
;; Block per Pick oder Namensmuster waehlen.
;; Rueckgabe: Namensmuster (String) oder nil bei Enter ("alle").
(defun ssg-bt-muster-waehlen (text / sel ed)
(initget "Name")
(setq sel (entsel text))
(cond
((null sel) nil)
((= (type sel) 'STR)
(setq sel (getstring T (ssg-text "bt-prompt-muster")))
(if (= sel "") nil sel)
)
(t
(setq ed (entget (car sel)))
(if (= (cdr (assoc 0 ed)) "INSERT")
(ssg-bt-muster-escape (ssg-bt-effname (car sel)))
(progn (prompt (ssg-text "bt-kein-block")) nil)
)
)
)
)
;; Attribute EINER Einfuegung ersetzen (oder nur zaehlen, wenn probe-p).
;; tag = wcmatch-Muster fuer den Attribut-Tag ("*" = alle).
;; Rueckgabe: Anzahl betroffener Attribute.
(defun ssg-bt-attr-ersetzen-ent (ent tag suche ersatz teil-p probe-p
/ e ed neu n)
(setq n 0
e (entnext ent))
(while (and e
(= "ATTRIB" (cdr (assoc 0 (setq ed (entget e))))))
(if (and (ssg-bt-name-passt-p (cdr (assoc 2 ed)) tag)
(setq neu (ssg-bt-wert-neu (cdr (assoc 1 ed)) suche ersatz teil-p)))
(progn
(setq n (1+ n))
(if (not probe-p)
(entmod (subst (cons 1 neu) (assoc 1 ed) ed))
)
)
)
(setq e (entnext e))
)
(if (and (> n 0) (not probe-p)) (entupd ent))
n
)
;; Attribute einer Liste von Einfuegungen ersetzen. Rueckgabe: Anzahl.
(defun ssg-bt-attr-ersetzen-liste (ents tag suche ersatz teil-p probe-p / n)
(setq n 0)
(foreach ent ents
(setq n (+ n (ssg-bt-attr-ersetzen-ent ent tag suche ersatz teil-p probe-p)))
)
n
)
;; Auswahlsatz -> Liste von Entity-Namen (nur INSERT)
(defun ssg-bt-ss-inserts (ss / i ent res)
(if ss
(progn
(setq i 0)
(while (setq ent (ssname ss i))
(if (= (cdr (assoc 0 (entget ent))) "INSERT")
(setq res (cons ent res))
)
(setq i (1+ i))
)
)
)
(reverse res)
)
;; ------------------------------------------------------------
;; BEFEHLE
;; ------------------------------------------------------------
(defun c:SSG_BLOCK_COUNT ( / muster stat summe)
(setq muster (ssg-bt-muster-waehlen (ssg-text "bt-prompt-waehlen-count")))
(setq stat (ssg-bt-statistik muster))
(cond
((null stat)
(prompt (if muster
(ssg-textf "bt-count-keine" (list (ssg-bt-muster-anzeige muster)))
(ssg-text "bt-count-keine-alle")))
)
((and muster (null (cdr stat)))
(prompt (ssg-textf "bt-count-ergebnis" (list (cdar stat) (caar stat))))
)
(t
(setq summe 0)
(foreach z stat
(prompt (ssg-textf "bt-count-zeile" (list (car z) (cdr z))))
(setq summe (+ summe (cdr z)))
)
(prompt (ssg-textf "bt-count-summe" (list summe (length stat))))
)
)
(princ)
)
(defun c:SSG_BLOCK_DELETE ( / muster ents frei gesperrt n)
(setq muster (ssg-bt-muster-waehlen (ssg-text "bt-prompt-waehlen-delete")))
(if (null muster)
(prompt (ssg-text "bt-delete-kein-muster"))
(progn
(setq ents (ssg-bt-inserts muster))
(foreach ent ents
(if (ssg-bt-layer-gesperrt-p ent)
(setq gesperrt (cons ent gesperrt))
(setq frei (cons ent frei))
)
)
(cond
((null ents)
(prompt (ssg-textf "bt-count-keine" (list (ssg-bt-muster-anzeige muster)))))
((null frei)
(prompt (ssg-textf "bt-delete-alle-gesperrt" (list (length gesperrt)))))
((ssg-in-yesno (ssg-textf "bt-delete-frage" (list (length frei) (ssg-bt-muster-anzeige muster))) nil)
(ssg-start (ssg-text "bt-delete-titel") nil)
(setq n 0)
(foreach ent frei
(if (entdel ent) (setq n (1+ n)))
)
(ssg-end)
(prompt (ssg-textf "bt-delete-ergebnis" (list n)))
(if gesperrt
(prompt (ssg-textf "bt-delete-gesperrt" (list (length gesperrt)))))
)
(t (prompt (ssg-text "bt-abgebrochen")))
)
)
)
(princ)
)
(defun c:SSG_ATTR_ERSETZEN ( / k-bereich k-modus bereich ents muster tag suche ersatz modus teil-p n)
(setq k-bereich (ssg-text "in-keys-bereich")
k-modus (ssg-text "in-keys-modus")
bereich (ssg-in-keyword (ssg-text "bt-attr-bereich") k-bereich
(ssg-in-first-word k-bereich)))
(if (= bereich (ssg-in-first-word k-bereich))
(progn
(setq muster (ssg-in-string (ssg-text "bt-attr-muster") "*"))
(setq ents (ssg-bt-inserts muster))
)
(progn
(prompt (ssg-text "bt-attr-auswahl"))
(setq ents (ssg-bt-ss-inserts (ssget '((0 . "INSERT")))))
)
)
(cond
((null ents) (prompt (ssg-text "bt-attr-keine-bloecke")))
(t
(setq tag (ssg-in-string (ssg-text "bt-attr-tag") "*")
suche (ssg-in-string (ssg-text "bt-attr-suche") nil))
(if (or (null suche) (= suche ""))
(prompt (ssg-text "bt-abgebrochen"))
(progn
(setq ersatz (ssg-in-string (ssg-text "bt-attr-ersatz") "")
modus (ssg-in-keyword (ssg-text "bt-attr-modus") k-modus
(ssg-in-first-word k-modus))
teil-p (= modus (ssg-in-first-word k-modus)))
(setq n (ssg-bt-attr-ersetzen-liste ents tag suche ersatz teil-p T))
(cond
((= n 0) (prompt (ssg-text "bt-attr-nichts")))
((ssg-in-yesno (ssg-textf "bt-attr-frage" (list n (length ents))) T)
(ssg-start (ssg-text "bt-attr-titel") nil)
(setq n (ssg-bt-attr-ersetzen-liste ents tag suche ersatz teil-p nil))
(ssg-end)
(prompt (ssg-textf "bt-attr-ergebnis" (list n))))
(t (prompt (ssg-text "bt-abgebrochen")))
)
)
)
)
)
(princ)
)
(princ)
+162
View File
@@ -0,0 +1,162 @@
;; ============================================================
;; SSG_INPUT.LSP - Generische Eingabe-Wrapper (ssg-in-*)
;;
;; Allgemeingueltige Abfragen mit Vorgabewert, Anzeige "<Vorgabe>" im
;; Prompt und Enter = Vorgabe (Idee von g_in/g_ky aus den ACADSST-
;; Makros). Steht NEBEN den VF-spezifischen vfl-in-* aus
;; vf_linienzug.lsp; diese bleiben unveraendert.
;;
;; Alle Funktionen liefern den eingegebenen Wert oder die Vorgabe.
;; ESC bricht wie ueblich ueber *error* ab (z.B. ssg-errhan).
;; Ist kein Wert eingegeben und keine Vorgabe da, ist die Rueckgabe nil.
;;
;; Optionaler Hook (z.B. fuer ein Eingabe-Journal):
;; (setq *ssg-in-hook* 'meine-funktion)
;; (defun meine-funktion (art prompt wert) ...) ;; art = "REAL" "INT"
;; ;; "STRING" "POINT"
;; ;; "DIST" "KEYWORD"
;; ;; "YESNO"
;; Ein Hook, der einen Fehler wirft, wird abgeschaltet.
;;
;; Setzt ssg_core.lsp (und fuer ssg-in-yesno ssg_lang.lsp) voraus.
;; ============================================================
(vl-load-com)
;; ------------------------------------------------------------
;; REINE HILFSFUNKTIONEN (ohne Zeichnung, in test_unit getestet)
;; ------------------------------------------------------------
;; Vorgabe einsetzen, wenn kein Wert eingegeben wurde
(defun ssg-in-default (wert default)
(if wert wert default)
)
;; Reelle Zahl ohne ueberfluessige Nullen: 5.0 -> "5", 2.50 -> "2.5"
(defun ssg-in-fmt-real (v / s)
(setq s (rtos v 2 6))
(if (vl-string-position 46 s)
(progn
(while (= (substr s (strlen s)) "0")
(setq s (substr s 1 (1- (strlen s))))
)
(if (= (substr s (strlen s)) ".")
(setq s (substr s 1 (1- (strlen s))))
)
)
)
s
)
;; Punkt als "x,y,z" (fehlende Z-Werte als 0)
(defun ssg-in-fmt-pt (p)
(strcat (ssg-in-fmt-real (car p)) ","
(ssg-in-fmt-real (cadr p)) ","
(ssg-in-fmt-real (if (caddr p) (caddr p) 0.0)))
)
;; Prompt aufbauen: "<text> <default>: " bzw. "<text>: " ohne Vorgabe
(defun ssg-in-prompt (text default-str)
(strcat text
(if default-str (strcat " <" default-str ">") "")
": ")
)
;; Erstes Wort eines Schluesselwort-Strings: "Ja Nein" -> "Ja"
(defun ssg-in-first-word (schluessel / pos)
(if (setq pos (vl-string-search " " schluessel))
(substr schluessel 1 pos)
schluessel
)
)
;; Zweites Wort: "Ja Nein" -> "Nein"
(defun ssg-in-second-word (schluessel / pos)
(if (setq pos (vl-string-search " " schluessel))
(substr schluessel (+ pos 2))
""
)
)
;; ------------------------------------------------------------
;; HOOK
;; ------------------------------------------------------------
(defun ssg-in-notify (art text wert / res)
(if *ssg-in-hook*
(progn
(setq res (vl-catch-all-apply *ssg-in-hook* (list art text wert)))
(if (vl-catch-all-error-p res) (setq *ssg-in-hook* nil))
)
)
wert
)
;; ------------------------------------------------------------
;; ABFRAGEN
;; text = Prompt ohne Doppelpunkt, z.B. "\nHoehe"
;; ------------------------------------------------------------
(defun ssg-in-real (text default / w)
(setq w (getreal (ssg-in-prompt text (if default (ssg-in-fmt-real default)))))
(ssg-in-notify "REAL" text (ssg-in-default w default))
)
(defun ssg-in-int (text default / w)
(setq w (getint (ssg-in-prompt text (if default (itoa default)))))
(ssg-in-notify "INT" text (ssg-in-default w default))
)
;; String (mit Leerzeichen). Enter ohne Eingabe -> Vorgabe.
(defun ssg-in-string (text default / w)
(setq w (getstring T (ssg-in-prompt text default)))
(if (= w "") (setq w nil))
(ssg-in-notify "STRING" text (ssg-in-default w default))
)
;; Punkt. base = Gummiband-Basispunkt oder nil, default = Punkt oder nil.
(defun ssg-in-point (text default base / w)
(setq w (if base
(getpoint base (ssg-in-prompt text (if default (ssg-in-fmt-pt default))))
(getpoint (ssg-in-prompt text (if default (ssg-in-fmt-pt default))))
))
(ssg-in-notify "POINT" text (ssg-in-default w default))
)
;; Abstand. base = Basispunkt oder nil.
(defun ssg-in-dist (text default base / w)
(setq w (if base
(getdist base (ssg-in-prompt text (if default (ssg-in-fmt-real default))))
(getdist (ssg-in-prompt text (if default (ssg-in-fmt-real default))))
))
(ssg-in-notify "DIST" text (ssg-in-default w default))
)
;; Schluesselwort ohne Hook (intern, auch von ssg-in-yesno genutzt).
(defun ssg-in-keyword-raw (text schluessel default / w)
(initget 0 schluessel)
(setq w (getkword
(ssg-in-prompt
(strcat text " [" (vl-string-translate " " "/" schluessel) "]")
default)))
(ssg-in-default w default)
)
;; Schluesselwort. schluessel im initget-Format, z.B. "Alle Auswahl".
;; Rueckgabe: gewaehltes Schluesselwort (volle Schreibweise) oder default.
(defun ssg-in-keyword (text schluessel default)
(ssg-in-notify "KEYWORD" text (ssg-in-keyword-raw text schluessel default))
)
;; Ja/Nein-Abfrage, Rueckgabe T bei Ja, nil bei Nein (anders als ssg-ques,
;; das T fuer die NICHT-vorgegebene Antwort liefert).
;; default = T -> Enter bedeutet Ja, nil -> Enter bedeutet Nein.
;; Die Schluesselwoerter kommen aus ssg-text "in-yesno-keys" (z.B. "Ja Nein").
(defun ssg-in-yesno (text default / schluessel ja nein w)
(setq schluessel (ssg-text "in-yesno-keys")
ja (ssg-in-first-word schluessel)
nein (ssg-in-second-word schluessel))
(setq w (ssg-in-keyword-raw text schluessel (if default ja nein)))
(ssg-in-notify "YESNO" text (= w ja))
)
(princ)
+5 -1
View File
@@ -28,6 +28,7 @@
(load (strcat base-path "ssg_dbg.lsp") "ssg_dbg.lsp nicht gefunden")
(load (strcat base-path "ssg_dialog.lsp") "ssg_dialog.lsp nicht gefunden")
(load (strcat base-path "ssg_layer.lsp") "ssg_layer.lsp nicht gefunden")
(load (strcat base-path "ssg_input.lsp") "ssg_input.lsp nicht gefunden")
;; Gemeinsame KS-Extraktion + Einfuegeprimitiven - MUSS vor VarioFoerderer
;; und Gefaellestrecke geladen werden (beide nutzen sie).
(load (strcat base-path "ssg_ks_insert.lsp") "ssg_ks_insert.lsp nicht gefunden")
@@ -39,7 +40,10 @@
(load (strcat base-path "Tro_Edit.lsp") "Tro_Edit.lsp nicht gefunden")
(load (strcat base-path "Connection_Edit.lsp") "Connection_Edit.lsp nicht gefunden")
(load (strcat base-path "SSG_LIB_Commands.lsp") "SSG_LIB_Commands.lsp nicht gefunden")
(prompt "\nSSG-Bibliotheken geladen: ssg_core, ssg_lang, ssg_dbg, ssg_dialog, ssg_layer, KreiselInsert, VarioFoerderer, Gefaellestrecke, export, OmniModulInsert, SSG_LIB_Commands")
;; Werkzeuge: ssg_texttools nutzt ssg_blocktools, beide nutzen ssg_input
(load (strcat base-path "ssg_blocktools.lsp") "ssg_blocktools.lsp nicht gefunden")
(load (strcat base-path "ssg_texttools.lsp") "ssg_texttools.lsp nicht gefunden")
(prompt "\nSSG-Bibliotheken geladen: ssg_core, ssg_lang, ssg_dbg, ssg_dialog, ssg_layer, ssg_input, KreiselInsert, VarioFoerderer, Gefaellestrecke, export, OmniModulInsert, SSG_LIB_Commands, ssg_blocktools, ssg_texttools")
(princ)
)
+285
View File
@@ -0,0 +1,285 @@
;; ============================================================
;; SSG_TEXTTOOLS.LSP - Text-Werkzeuge
;;
;; Ursprung: ACADSST/MENU/CHGTEXT.LSP (Suchen/Ersetzen), PARTEXT.LSP
;; (Tbpl: parallel beschriften), ALTHOEHE.LSP (Tsz), ALTSTIL.LSP (Ts).
;; Neu geschrieben im ssg-Stil (Undo-Gruppe, i18n, ssg-in-*).
;;
;; Befehle:
;; SSG_TEXT_ERSETZEN Zeichenketten in TEXT, MTEXT und Block-
;; Attributen suchen/ersetzen (mit Vorschau)
;; SSG_TEXT_PARALLEL Text parallel zu Linie/Polylinie/Bogen setzen
;; (lesbar ausgerichtet, mit Abstand zur Linie)
;; SSG_TEXT_HOEHE Texthoehe von TEXT/MTEXT aendern
;; SSG_TEXT_STIL Textstil von TEXT/MTEXT aendern
;;
;; Arbeitet in der XY-Ebene des Welt-KS (Textrotation = WKS-Winkel).
;; Setzt ssg_core.lsp, ssg_lang.lsp, ssg_input.lsp und ssg_blocktools.lsp
;; (ssg-bt-wert-neu, ssg-bt-attr-ersetzen-ent) voraus.
;; ============================================================
(vl-load-com)
;; ------------------------------------------------------------
;; REINE HILFSFUNKTIONEN (in test_unit getestet)
;; ------------------------------------------------------------
;; Winkel (Bogenmass) so drehen, dass ein Text lesbar bleibt: Winkel im
;; Bereich (90 Grad, 270 Grad] werden um 180 Grad gedreht. Ergebnis in
;; [0, 2*pi).
(defun ssg-tt-lesbarer-winkel (a)
(setq a (rem a (* 2.0 pi)))
(if (< a 0.0) (setq a (+ a (* 2.0 pi))))
(if (and (> a (+ (/ pi 2.0) 1e-9))
(<= a (+ (* 1.5 pi) 1e-9)))
(setq a (- a pi))
)
(if (< a 0.0) (setq a (+ a (* 2.0 pi))))
a
)
;; Punkt um abstand in Richtung winkel verschieben (2D, Z bleibt erhalten)
(defun ssg-tt-versetzt (p winkel abstand)
(list (+ (car p) (* abstand (cos winkel)))
(+ (cadr p) (* abstand (sin winkel)))
(if (caddr p) (caddr p) 0.0))
)
;; ------------------------------------------------------------
;; AUSWAHL
;; ------------------------------------------------------------
;; Auswahlsatz der angegebenen Typen holen (z.B. "TEXT,MTEXT,INSERT").
;; alle-p = T -> alle im aktuellen Layout, nil -> Benutzerwahl
(defun ssg-tt-ss-holen (alle-p typen)
(if alle-p
(ssget "_X" (list (cons 0 typen) (cons 410 (getvar "CTAB"))))
(ssget (list (cons 0 typen)))
)
)
;; Auswahlsatz -> Liste von Entity-Namen mit Typ-Filter ("TEXT" "MTEXT" ...)
(defun ssg-tt-ss-liste (ss typen / i ent res)
(if ss
(progn
(setq i 0)
(while (setq ent (ssname ss i))
(if (member (cdr (assoc 0 (entget ent))) typen)
(setq res (cons ent res))
)
(setq i (1+ i))
)
)
)
(reverse res)
)
;; ------------------------------------------------------------
;; SUCHEN / ERSETZEN
;; ------------------------------------------------------------
;; TEXT/MTEXT-Inhalte ersetzen (oder nur zaehlen). Rueckgabe: Anzahl Texte.
(defun ssg-tt-text-ersetzen-liste (ents suche ersatz teil-p probe-p
/ n obj alt neu)
(setq n 0)
(foreach ent ents
(setq obj (vlax-ename->vla-object ent)
alt (vla-get-textstring obj)
neu (ssg-bt-wert-neu alt suche ersatz teil-p))
(if neu
(if probe-p
(setq n (1+ n))
(if (not (vl-catch-all-error-p
(vl-catch-all-apply 'vla-put-textstring (list obj neu))))
(setq n (1+ n))
)
)
)
)
n
)
;; Texte + Attribute in einem Auswahlsatz ersetzen/zaehlen.
;; Rueckgabe: (anzahl-texte . anzahl-attribute)
(defun ssg-tt-ersetzen-ss (ss suche ersatz teil-p probe-p)
(cons
(ssg-tt-text-ersetzen-liste
(ssg-tt-ss-liste ss '("TEXT" "MTEXT")) suche ersatz teil-p probe-p)
(ssg-bt-attr-ersetzen-liste
(ssg-tt-ss-liste ss '("INSERT")) "*" suche ersatz teil-p probe-p)
)
)
(defun c:SSG_TEXT_ERSETZEN ( / k-bereich k-modus alle-p ss suche ersatz modus teil-p z)
(setq k-bereich (ssg-text "in-keys-bereich")
k-modus (ssg-text "in-keys-modus")
alle-p (= (ssg-in-keyword (ssg-text "tt-bereich") k-bereich
(ssg-in-first-word k-bereich))
(ssg-in-first-word k-bereich)))
(if (not alle-p) (prompt (ssg-text "tt-auswahl")))
(setq ss (ssg-tt-ss-holen alle-p "TEXT,MTEXT,INSERT"))
(if (null ss)
(prompt (ssg-text "tt-keine-objekte"))
(progn
(setq suche (ssg-in-string (ssg-text "tt-suche") nil))
(if (or (null suche) (= suche ""))
(prompt (ssg-text "tt-abgebrochen"))
(progn
(setq ersatz (ssg-in-string (ssg-text "tt-ersatz") "")
modus (ssg-in-keyword (ssg-text "tt-modus") k-modus
(ssg-in-first-word k-modus))
teil-p (= modus (ssg-in-first-word k-modus)))
(setq z (ssg-tt-ersetzen-ss ss suche ersatz teil-p T))
(cond
((= 0 (+ (car z) (cdr z))) (prompt (ssg-text "tt-nichts")))
((ssg-in-yesno (ssg-textf "tt-frage" (list (car z) (cdr z))) T)
(ssg-start (ssg-text "tt-ersetzen-titel") nil)
(setq z (ssg-tt-ersetzen-ss ss suche ersatz teil-p nil))
(ssg-end)
(prompt (ssg-textf "tt-ergebnis" (list (car z) (cdr z)))))
(t (prompt (ssg-text "tt-abgebrochen")))
)
)
)
)
)
(princ)
)
;; ------------------------------------------------------------
;; PARALLEL BESCHRIFTEN
;; ------------------------------------------------------------
;; Winkel der Kurve (Linie, Polylinie, Bogen, ...) am Punkt pt (WKS).
;; Rueckgabe: Winkel in Bogenmass oder nil, wenn nicht ermittelbar.
(defun ssg-tt-kurven-winkel (ent pt / obj cp param deriv)
(setq obj (vlax-ename->vla-object ent))
(setq cp (vl-catch-all-apply 'vlax-curve-getclosestpointto (list obj pt)))
(if (or (vl-catch-all-error-p cp) (null cp))
nil
(progn
(setq param (vl-catch-all-apply 'vlax-curve-getparamatpoint (list obj cp)))
(if (or (vl-catch-all-error-p param) (null param))
nil
(progn
(setq deriv (vl-catch-all-apply 'vlax-curve-getfirstderiv (list obj param)))
(if (or (vl-catch-all-error-p deriv) (null deriv))
nil
(list (atan (cadr deriv) (car deriv)) cp)
)
)
)
)
)
)
;; TEXT erzeugen (unten mittig, Gruppe 73 = 1 damit Gruppe 11 gilt)
(defun ssg-tt-text-machen (p hoehe string winkel)
(entmake (list '(0 . "TEXT")
(cons 8 (getvar "CLAYER"))
(cons 7 (getvar "TEXTSTYLE"))
(cons 10 p)
(cons 11 p)
(cons 40 hoehe)
(cons 1 string)
(cons 50 winkel)
(cons 72 1)
(cons 73 1)))
)
(defun c:SSG_TEXT_PARALLEL ( / sel info a ar p text)
(ssg-start (ssg-text "tt-parallel-titel") nil)
(if (or (null *ssg-tt-hoehe*) (<= *ssg-tt-hoehe* 0.0))
(setq *ssg-tt-hoehe* (if (> (getvar "TEXTSIZE") 0.0) (getvar "TEXTSIZE") 2.5))
)
(setq *ssg-tt-hoehe* (ssg-in-real (ssg-text "tt-hoehe") *ssg-tt-hoehe*))
(if (null *ssg-tt-abstand*)
(setq *ssg-tt-abstand* (* 0.5 *ssg-tt-hoehe*))
)
(setq *ssg-tt-abstand* (ssg-in-real (ssg-text "tt-abstand") *ssg-tt-abstand*))
(while (setq sel (entsel (ssg-text "tt-parallel-waehlen")))
(setq info (ssg-tt-kurven-winkel (car sel) (trans (cadr sel) 1 0)))
(if (null info)
(prompt (ssg-text "tt-parallel-keine-kurve"))
(progn
(setq a (car info)
ar (ssg-tt-lesbarer-winkel a)
p (ssg-tt-versetzt (cadr info) (+ ar (/ pi 2.0)) *ssg-tt-abstand*)
text (ssg-in-string (ssg-text "tt-text") *ssg-tt-text*))
(if (and text (/= text ""))
(progn
(setq *ssg-tt-text* text)
(if (not (ssg-tt-text-machen p *ssg-tt-hoehe* text ar))
(prompt (ssg-text "tt-parallel-fehler"))
)
)
)
)
)
)
(ssg-end)
(princ)
)
;; ------------------------------------------------------------
;; HOEHE / STIL AENDERN
;; ------------------------------------------------------------
(defun c:SSG_TEXT_HOEHE ( / ents hoehe n)
(prompt (ssg-text "tt-auswahl"))
(setq ents (ssg-tt-ss-liste (ssget '((0 . "TEXT,MTEXT"))) '("TEXT" "MTEXT")))
(if (null ents)
(prompt (ssg-text "tt-keine-objekte"))
(progn
(setq hoehe (ssg-in-real (ssg-text "tt-hoehe")
(if (> (getvar "TEXTSIZE") 0.0) (getvar "TEXTSIZE") nil)))
(if (or (null hoehe) (<= hoehe 0.0))
(prompt (ssg-text "tt-abgebrochen"))
(progn
(ssg-start (ssg-text "tt-hoehe-titel") nil)
(setq n 0)
(foreach ent ents
(if (not (vl-catch-all-error-p
(vl-catch-all-apply 'vla-put-height
(list (vlax-ename->vla-object ent) hoehe))))
(setq n (1+ n))
)
)
(ssg-end)
(prompt (ssg-textf "tt-geaendert" (list n)))
)
)
)
)
(princ)
)
(defun c:SSG_TEXT_STIL ( / ents stil n)
(prompt (ssg-text "tt-auswahl"))
(setq ents (ssg-tt-ss-liste (ssget '((0 . "TEXT,MTEXT"))) '("TEXT" "MTEXT")))
(if (null ents)
(prompt (ssg-text "tt-keine-objekte"))
(progn
(setq stil (ssg-in-string (ssg-text "tt-stil") (getvar "TEXTSTYLE")))
(cond
((or (null stil) (null (tblsearch "STYLE" stil)))
(prompt (ssg-textf "tt-stil-fehlt" (list (if stil stil "")))))
(t
(ssg-start (ssg-text "tt-stil-titel") nil)
(setq n 0)
(foreach ent ents
(if (not (vl-catch-all-error-p
(vl-catch-all-apply 'vla-put-stylename
(list (vlax-ename->vla-object ent) stil))))
(setq n (1+ n))
)
)
(ssg-end)
(prompt (ssg-textf "tt-geaendert" (list n))))
)
)
)
(princ)
)
(princ)
+26 -6
View File
@@ -6,11 +6,12 @@ REM Zeichnet jede Zeile der Export-CSV (EXPORTCSV) als achsparalleles
REM Rechteck aus Position + Boundingbox, mit Legende und Tooltip je
REM Rechteck sowie den Anschluss-Koordinatensystemen K1-K4 (rotes Kreuz,
REM blaue Linie K1->K2->K3->K4), und oeffnet das Ergebnis im Browser.
REM Optional zusaetzlich Materialfluss- und Bahnzusammenhang-Graph.
REM Optional zusaetzlich Materialfluss-, Bahnzusammenhang- und TRO-Fluss-Graph.
REM
REM Die Darstellung uebernimmt sps_skel (bin\material_flow.bat,
REM Option --show-bbs). sps_skel wird neben dxfmakros erwartet
REM (..\sps_skel) oder ueber die Umgebungsvariable SPS_SKEL_HOME.
REM Option --show-bbs, bzw. bin\tro_flow.bat fuer 'tro'). sps_skel wird
REM neben dxfmakros erwartet (..\sps_skel) oder ueber die Umgebungs-
REM variable SPS_SKEL_HOME.
REM
REM Aufruf:
REM bin\show_exportcsv.bat results\export.csv, alle Zeilen
@@ -18,13 +19,15 @@ REM bin\show_exportcsv.bat meine_export.csv andere CSV in results\ (oder Pf
REM bin\show_exportcsv.bat export.csv flow ohne VF/GF-Einzelbausteine
REM bin\show_exportcsv.bat export.csv mflow zusaetzlich Materialfluss-Graph
REM bin\show_exportcsv.bat export.csv track zusaetzlich Bahnzusammenhang-Graph
REM bin\show_exportcsv.bat export.csv flow mflow track alles kombiniert
REM bin\show_exportcsv.bat export.csv tro zusaetzlich TRO-Fluss-Graph (lagerichtig)
REM bin\show_exportcsv.bat export.csv flow mflow track tro alles kombiniert
REM
REM mflow/track brauchen Graphviz ('dot' im PATH).
REM mflow/track/tro brauchen Graphviz ('dot' bzw. 'neato' im PATH).
REM
REM Ergebnis: %SKEL_RESULTS%\<name>_bbs.svg
REM %SKEL_RESULTS%\<name>_material_flow.svg (nur mit 'mflow')
REM %SKEL_RESULTS%\<name>_track.svg (nur mit 'track')
REM %SKEL_RESULTS%\<name>_tro_flow.svg (nur mit 'tro')
REM ================================================================
setlocal
@@ -58,20 +61,24 @@ for %%F in ("%CSV%") do (
set "SVG=%SKEL_RESULTS%\%%~nF_bbs.svg"
set "MF_SVG=%SKEL_RESULTS%\%%~nF_material_flow.svg"
set "TRACK_SVG=%SKEL_RESULTS%\%%~nF_track.svg"
set "TRO_SVG=%SKEL_RESULTS%\%%~nF_tro_flow.svg"
)
REM Weitere Argumente (Reihenfolge beliebig):
REM all (Default) / flow - Darstellungsmodus der Boundingbox-Ansicht
REM mflow - zusaetzlich Materialfluss-SVG erzeugen und oeffnen
REM track - zusaetzlich Bahnzusammenhang-SVG erzeugen und oeffnen
REM tro - zusaetzlich TRO-Fluss-SVG (lagerichtig) erzeugen und oeffnen
set "MODE=all"
set "MFLOW="
set "TRACK="
for %%A in (%2 %3 %4) do (
set "TRO="
for %%A in (%2 %3 %4 %5) do (
if /i "%%~A"=="all" set "MODE=all"
if /i "%%~A"=="flow" set "MODE=flow"
if /i "%%~A"=="mflow" set "MFLOW=1"
if /i "%%~A"=="track" set "TRACK=1"
if /i "%%~A"=="tro" set "TRO=1"
)
REM Beide Graphen entstehen erst mit --tosvg (Graphviz 'dot')
@@ -83,10 +90,15 @@ REM Alte SVGs entfernen, damit nie eine veraltete Ansicht geoeffnet wird
if exist "%SVG%" del "%SVG%"
if defined MFLOW if exist "%MF_SVG%" del "%MF_SVG%"
if defined TRACK if exist "%TRACK_SVG%" del "%TRACK_SVG%"
if defined TRO if exist "%TRO_SVG%" del "%TRO_SVG%"
call "%SPS_SKEL_HOME%\bin\material_flow.bat" --file "%CSV%" --show-bbs %MODE% --show-kx %OPTS%
set "RC=%ERRORLEVEL%"
if defined TRO (
call "%SPS_SKEL_HOME%\bin\tro_flow.bat" --file "%CSV%" --tosvg --use-cords
)
if not exist "%SVG%" (
echo FEHLER: SVG wurde nicht erzeugt ^(material_flow Exit-Code %RC%^).
endlocal & exit /b 1
@@ -115,6 +127,14 @@ if defined TRACK (
echo WARNUNG: Bahnzusammenhang-SVG wurde nicht erzeugt ^(Graphviz 'dot' vorhanden?^).
)
)
if defined TRO (
if exist "%TRO_SVG%" (
echo TRO-Fluss: %TRO_SVG%
start "" "%TRO_SVG%"
) else (
echo WARNUNG: TRO-Fluss-SVG wurde nicht erzeugt ^(Graphviz 'neato' vorhanden?^).
)
)
endlocal & exit /b 0
+7212
View File
File diff suppressed because it is too large Load Diff
+55 -1
View File
@@ -1040,6 +1040,60 @@
"gr-tr-beschr-stil-fehlt": "\nTextstil %1 fehlt in der Zeichnung - Beschriftung mit aktuellem Stil %2.",
"gr-tr-beschr-ausrichtung": "\nUnbekannte Ausrichtung %1 fuer die Traeger-Beschriftung - verwende BC.",
"gr-tr-beschr-ergebnis": "\n%1 Traeger beschriftet (davon %2 ohne bekannte Variante), %3 nicht beschriftbar, %4 verwaiste Beschriftungen entfernt.",
"gr-tr-beschr-keine": "\nKeine Rohr-Geruest-Traeger in der Zeichnung."
"gr-tr-beschr-keine": "\nKeine Rohr-Geruest-Traeger in der Zeichnung.",
"in-yesno-keys": "Ja Nein",
"in-keys-bereich": "Alle Auswahl",
"in-keys-modus": "Teil Gesamt",
"bt-prompt-muster": "\nBlockname oder Muster (z.B. GR_*): ",
"bt-kein-block": "\nDas gewaehlte Objekt ist keine Blockeinfuegung.",
"bt-prompt-waehlen-count": "\nBlock waehlen [Name/Muster] <alle Bloecke>: ",
"bt-count-keine": "\nKeine Einfuegungen von %1 gefunden.",
"bt-count-keine-alle": "\nKeine Blockeinfuegungen im aktuellen Layout.",
"bt-count-ergebnis": "\n%1 Einfuegung(en) von %2.",
"bt-count-zeile": "\n %1: %2",
"bt-count-summe": "\nGesamt: %1 Einfuegung(en) in %2 Block(s).",
"bt-prompt-waehlen-delete": "\nZu loeschenden Block waehlen [Name/Muster]: ",
"bt-delete-kein-muster": "\nKein Block gewaehlt - nichts geloescht.",
"bt-delete-alle-gesperrt": "\nAlle %1 Einfuegung(en) liegen auf gesperrten Layern - nichts geloescht.",
"bt-delete-frage": "%1 Einfuegung(en) von %2 loeschen?",
"bt-delete-titel": "Bloecke loeschen",
"bt-delete-ergebnis": "\n%1 Einfuegung(en) geloescht.",
"bt-delete-gesperrt": "\n%1 Einfuegung(en) auf gesperrten Layern blieben stehen.",
"bt-abgebrochen": "\nAbgebrochen - nichts geaendert.",
"bt-attr-bereich": "\nBereich",
"bt-attr-muster": "\nBlockname-Muster",
"bt-attr-auswahl": "\nBloecke waehlen: ",
"bt-attr-keine-bloecke": "\nKeine passenden Blockeinfuegungen gefunden.",
"bt-attr-tag": "\nAttribut-Tag (Muster)",
"bt-attr-suche": "\nSuchen nach",
"bt-attr-ersatz": "\nErsetzen durch",
"bt-attr-modus": "\nErsetzen als",
"bt-attr-nichts": "\nKein Attributwert enthaelt den Suchtext.",
"bt-attr-frage": "%1 Attributwert(e) in %2 Block(s) aendern?",
"bt-attr-titel": "Attribute ersetzen",
"bt-attr-ergebnis": "\n%1 Attributwert(e) geaendert.",
"tt-bereich": "\nBereich",
"tt-auswahl": "\nObjekte waehlen: ",
"tt-keine-objekte": "\nKeine passenden Objekte gefunden.",
"tt-suche": "\nSuchen nach",
"tt-ersatz": "\nErsetzen durch",
"tt-modus": "\nErsetzen als",
"tt-nichts": "\nKein Text und kein Attributwert enthaelt den Suchtext.",
"tt-frage": "%1 Text(e) und %2 Attributwert(e) aendern?",
"tt-ersetzen-titel": "Text ersetzen",
"tt-ergebnis": "\n%1 Text(e) und %2 Attributwert(e) geaendert.",
"tt-abgebrochen": "\nAbgebrochen - nichts geaendert.",
"tt-parallel-titel": "Text parallel beschriften",
"tt-hoehe": "\nTexthoehe",
"tt-abstand": "\nAbstand zur Linie",
"tt-parallel-waehlen": "\nLinie, Polylinie oder Bogen waehlen (Enter = Ende): ",
"tt-parallel-keine-kurve": "\nWinkel am gewaehlten Objekt nicht ermittelbar.",
"tt-text": "\nText",
"tt-parallel-fehler": "\nText konnte nicht erzeugt werden.",
"tt-hoehe-titel": "Texthoehe aendern",
"tt-geaendert": "\n%1 Text(e) geaendert.",
"tt-stil": "\nTextstil",
"tt-stil-fehlt": "\nTextstil %1 existiert nicht in der Zeichnung.",
"tt-stil-titel": "Textstil aendern"
}
}
+55 -1
View File
@@ -1040,6 +1040,60 @@
"gr-tr-beschr-stil-fehlt": "\nText style %1 missing in drawing - labelling with current style %2.",
"gr-tr-beschr-ausrichtung": "\nUnknown justification %1 for beam label - using BC.",
"gr-tr-beschr-ergebnis": "\n%1 beam(s) labelled (%2 without known variant), %3 not labellable, %4 orphaned label(s) removed.",
"gr-tr-beschr-keine": "\nNo pipe scaffold beams in the drawing."
"gr-tr-beschr-keine": "\nNo pipe scaffold beams in the drawing.",
"in-yesno-keys": "Yes No",
"in-keys-bereich": "All Selection",
"in-keys-modus": "Part Whole",
"bt-prompt-muster": "\nBlock name or pattern (e.g. GR_*): ",
"bt-kein-block": "\nThe selected object is not a block reference.",
"bt-prompt-waehlen-count": "\nSelect block [Name/pattern] <all blocks>: ",
"bt-count-keine": "\nNo references of %1 found.",
"bt-count-keine-alle": "\nNo block references in the current layout.",
"bt-count-ergebnis": "\n%1 reference(s) of %2.",
"bt-count-zeile": "\n %1: %2",
"bt-count-summe": "\nTotal: %1 reference(s) in %2 block(s).",
"bt-prompt-waehlen-delete": "\nSelect block to delete [Name/pattern]: ",
"bt-delete-kein-muster": "\nNo block selected - nothing deleted.",
"bt-delete-alle-gesperrt": "\nAll %1 reference(s) are on locked layers - nothing deleted.",
"bt-delete-frage": "Delete %1 reference(s) of %2?",
"bt-delete-titel": "Delete blocks",
"bt-delete-ergebnis": "\n%1 reference(s) deleted.",
"bt-delete-gesperrt": "\n%1 reference(s) on locked layers were kept.",
"bt-abgebrochen": "\nCancelled - nothing changed.",
"bt-attr-bereich": "\nScope",
"bt-attr-muster": "\nBlock name pattern",
"bt-attr-auswahl": "\nSelect blocks: ",
"bt-attr-keine-bloecke": "\nNo matching block references found.",
"bt-attr-tag": "\nAttribute tag (pattern)",
"bt-attr-suche": "\nFind",
"bt-attr-ersatz": "\nReplace with",
"bt-attr-modus": "\nReplace as",
"bt-attr-nichts": "\nNo attribute value contains the search text.",
"bt-attr-frage": "Change %1 attribute value(s) in %2 block(s)?",
"bt-attr-titel": "Replace attributes",
"bt-attr-ergebnis": "\n%1 attribute value(s) changed.",
"tt-bereich": "\nScope",
"tt-auswahl": "\nSelect objects: ",
"tt-keine-objekte": "\nNo matching objects found.",
"tt-suche": "\nFind",
"tt-ersatz": "\nReplace with",
"tt-modus": "\nReplace as",
"tt-nichts": "\nNo text or attribute value contains the search text.",
"tt-frage": "Change %1 text(s) and %2 attribute value(s)?",
"tt-ersetzen-titel": "Replace text",
"tt-ergebnis": "\n%1 text(s) and %2 attribute value(s) changed.",
"tt-abgebrochen": "\nCancelled - nothing changed.",
"tt-parallel-titel": "Label parallel to line",
"tt-hoehe": "\nText height",
"tt-abstand": "\nDistance to line",
"tt-parallel-waehlen": "\nSelect line, polyline or arc (Enter = finish): ",
"tt-parallel-keine-kurve": "\nCannot determine the angle on the selected object.",
"tt-text": "\nText",
"tt-parallel-fehler": "\nText could not be created.",
"tt-hoehe-titel": "Change text height",
"tt-geaendert": "\n%1 text(s) changed.",
"tt-stil": "\nText style",
"tt-stil-fehlt": "\nText style %1 does not exist in the drawing.",
"tt-stil-titel": "Change text style"
}
}
+6 -1
View File
@@ -2,7 +2,7 @@
;; SSG_LIB.mnl - Automatisch geladen beim MENULOAD von SSG_LIB.mnu
;;
;; Definiert den Lazy-Loader (ssg-ensure) und laedt alle Module.
;; Kern-Module: ssg_core, ssg_lang, ssg_dbg, ssg_dialog, ssg_layer, ssg_id
;; Kern-Module: ssg_core, ssg_lang, ssg_dbg, ssg_dialog, ssg_layer, ssg_id, ssg_input
;; Feature-Module: KreiselInsert, Gefaellestrecke, VarioFoerderer, ...
;; ============================================================
@@ -144,6 +144,8 @@
(ssg-ensure "ssg_dialog")
(ssg-ensure "ssg_layer")
(ssg-ensure "ssg_id")
;; Generische Eingabe-Wrapper (ssg-in-*), von den Werkzeug-Modulen genutzt
(ssg-ensure "ssg_input")
;; Gemeinsame KS-Extraktion + Block-Einfuegeprimitiven (von Gefaellestrecke
;; UND VarioFoerderer genutzt) - MUSS vor beiden geladen sein.
(ssg-ensure "ssg_ks_insert")
@@ -159,6 +161,9 @@
;; Tro_Edit wird nicht vorgeladen - der Dispatcher SSG_BLOCKEDIT und die
;; Menuemakros holen es per (ssg-ensure "Tro_Edit") bei Bedarf nach.
(ssg-ensure "SSG_LIB_Commands")
;; Werkzeuge (Reihenfolge: ssg_texttools nutzt ssg_blocktools)
(ssg-ensure "ssg_blocktools")
(ssg-ensure "ssg_texttools")
;; Menue einhaengen
(menucmd "P13=+SSG_LIB.POP1")
+9
View File
@@ -141,6 +141,15 @@
[Sprache]^C^C(ssg-ensure "SSG_LIB_Commands") SSG_SPRACHE
[Planquadrate an/aus]^C^C(ssg-ensure "DrawPlanquadrate") PLANQUADRATE_TOGGLE
[<-CSV-Export]^C^C(ssg-ensure "export") CSV_EXPORT_KONFIG
[->Werkzeuge]
[Bloecke zaehlen]^C^C(ssg-ensure "ssg_blocktools") SSG_BLOCK_COUNT
[Bloecke loeschen]^C^C(ssg-ensure "ssg_blocktools") SSG_BLOCK_DELETE
[Attribute ersetzen]^C^C(ssg-ensure "ssg_blocktools") SSG_ATTR_ERSETZEN
[--]
[Text ersetzen]^C^C(ssg-ensure "ssg_texttools") SSG_TEXT_ERSETZEN
[Text parallel beschriften]^C^C(ssg-ensure "ssg_texttools") SSG_TEXT_PARALLEL
[Texthoehe aendern]^C^C(ssg-ensure "ssg_texttools") SSG_TEXT_HOEHE
[<-Textstil aendern]^C^C(ssg-ensure "ssg_texttools") SSG_TEXT_STIL
[->Tests]
[alle Tests ausfuehren und exportieren]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_run_all.lsp")) (c:SSG_RUN_ALL_TESTS_EXPORT)
[Tests ausfuehren und stehen lassen]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_run_all.lsp")) (c:SSG_RUN_ALL_TESTS_OFFEN)
+73 -1
View File
@@ -1580,6 +1580,77 @@
(strcat "harter Fehler: " (vl-catch-all-error-message res))))
)
;; ------------------------------------------------------------
;; TESTS: ssg_input / ssg_blocktools / ssg_texttools - reine Funktionen
;; (die interaktiven Befehle SSG_BLOCK_*, SSG_ATTR_ERSETZEN, SSG_TEXT_*
;; brauchen eine Zeichnung und sind hier NICHT abgedeckt)
;; ------------------------------------------------------------
(defun tu-tests-werkzeuge ( / _e)
(princ "\n[ssg_input / ssg_blocktools / ssg_texttools]")
(if (not (and (car (atoms-family 1 '("SSG-IN-DEFAULT")))
(car (atoms-family 1 '("SSG-BT-WERT-NEU")))
(car (atoms-family 1 '("SSG-TT-LESBARER-WINKEL")))))
(tu-record nil "werkzeuge/geladen"
"ssg_input/ssg_blocktools/ssg_texttools nicht geladen (ssg_load.lsp)")
(progn
;; --- ssg_input ---
(tu-eqf "ssg-in-default/vorgabe" 5.0 (ssg-in-default nil 5.0))
(tu-eqf "ssg-in-default/eingabe" 3.0 (ssg-in-default 3.0 5.0))
(tu-nil "ssg-in-default/beides-nil" (ssg-in-default nil nil))
(tu-eq "ssg-in-fmt-real/ganz" "5" (ssg-in-fmt-real 5.0))
(tu-eq "ssg-in-fmt-real/halb" "2.5" (ssg-in-fmt-real 2.5))
(tu-eq "ssg-in-fmt-real/null" "0" (ssg-in-fmt-real 0.0))
(tu-eq "ssg-in-fmt-real/hundert" "100" (ssg-in-fmt-real 100.0))
(tu-eq "ssg-in-fmt-real/bruch" "0.125" (ssg-in-fmt-real 0.125))
(tu-eq "ssg-in-fmt-real/negativ" "-1.5" (ssg-in-fmt-real -1.5))
(tu-eq "ssg-in-fmt-pt/3d" "1,2.5,0" (ssg-in-fmt-pt '(1.0 2.5 0.0)))
(tu-eq "ssg-in-fmt-pt/2d" "1,2,0" (ssg-in-fmt-pt '(1.0 2.0)))
(tu-eq "ssg-in-prompt/mit-vorgabe" "\nHoehe <5>: " (ssg-in-prompt "\nHoehe" "5"))
(tu-eq "ssg-in-prompt/ohne" "\nHoehe: " (ssg-in-prompt "\nHoehe" nil))
(tu-eq "ssg-in-first-word" "Ja" (ssg-in-first-word "Ja Nein"))
(tu-eq "ssg-in-first-word/ein-wort" "Ja" (ssg-in-first-word "Ja"))
(tu-eq "ssg-in-second-word" "Nein" (ssg-in-second-word "Ja Nein"))
(tu-eq "ssg-in-second-word/ein-wort" "" (ssg-in-second-word "Ja"))
;; --- ssg_blocktools ---
(tu-true "ssg-bt-name-passt-p/muster" (ssg-bt-name-passt-p "GR_TR_1" "gr_*"))
(tu-nil "ssg-bt-name-passt-p/kein" (ssg-bt-name-passt-p "GR_TR_1" "XX*"))
(tu-true "ssg-bt-name-passt-p/nil" (ssg-bt-name-passt-p "ABC" nil))
(tu-true "ssg-bt-name-passt-p/leer" (ssg-bt-name-passt-p "ABC" ""))
(tu-true "ssg-bt-name-passt-p/escape-ja" (ssg-bt-name-passt-p "A.B" "A`.B"))
(tu-nil "ssg-bt-name-passt-p/escape-nein" (ssg-bt-name-passt-p "AxB" "A`.B"))
(tu-eq "ssg-bt-muster-escape" "A`.B`#1" (ssg-bt-muster-escape "A.B#1"))
(tu-eq "ssg-bt-muster-anzeige" "A.B#1" (ssg-bt-muster-anzeige "A`.B`#1"))
(tu-eq "ssg-bt-zaehle-namen"
'(("Alpha" . 1) ("Beta" . 1) ("Zeta" . 3))
(ssg-bt-zaehle-namen '("Zeta" "Alpha" "Zeta" "Beta" "Zeta")))
(tu-nil "ssg-bt-zaehle-namen/leer" (ssg-bt-zaehle-namen nil))
(tu-eq "ssg-bt-wert-neu/teil" "ABC_1" (ssg-bt-wert-neu "ABC-1" "-" "_" T))
(tu-eq "ssg-bt-wert-neu/mehrfach" "a.b.c" (ssg-bt-wert-neu "a-b-c" "-" "." T))
(tu-eq "ssg-bt-wert-neu/loeschen" "AC" (ssg-bt-wert-neu "ABC" "B" "" T))
(tu-nil "ssg-bt-wert-neu/kein-treffer" (ssg-bt-wert-neu "ABC" "X" "y" T))
(tu-eq "ssg-bt-wert-neu/gesamt-ja" "X" (ssg-bt-wert-neu "ABC" "ABC" "X" nil))
(tu-nil "ssg-bt-wert-neu/gesamt-nein" (ssg-bt-wert-neu "ABCD" "ABC" "X" nil))
(tu-nil "ssg-bt-wert-neu/leere-suche" (ssg-bt-wert-neu "ABC" "" "X" T))
(tu-nil "ssg-bt-wert-neu/gross-klein" (ssg-bt-wert-neu "abc" "ABC" "X" T))
;; --- ssg_texttools ---
(tu-eqf "ssg-tt-lesbarer-winkel/0" 0.0 (ssg-tt-lesbarer-winkel 0.0))
(tu-eqf "ssg-tt-lesbarer-winkel/45" (/ pi 4.0) (ssg-tt-lesbarer-winkel (/ pi 4.0)))
(tu-eqf "ssg-tt-lesbarer-winkel/90" (/ pi 2.0) (ssg-tt-lesbarer-winkel (/ pi 2.0)))
(tu-eqf "ssg-tt-lesbarer-winkel/135" (* 1.75 pi) (ssg-tt-lesbarer-winkel (* 0.75 pi)))
(tu-eqf "ssg-tt-lesbarer-winkel/180" 0.0 (ssg-tt-lesbarer-winkel pi))
(tu-eqf "ssg-tt-lesbarer-winkel/270" (/ pi 2.0) (ssg-tt-lesbarer-winkel (* 1.5 pi)))
(tu-eqf "ssg-tt-lesbarer-winkel/-45" (* 1.75 pi) (ssg-tt-lesbarer-winkel (- (/ pi 4.0))))
(tu-eqf "ssg-tt-lesbarer-winkel/360" 0.0 (ssg-tt-lesbarer-winkel (* 2.0 pi)))
(tu-eqf "ssg-tt-versetzt/x" '(5.0 0.0 0.0) (ssg-tt-versetzt '(0.0 0.0 0.0) 0.0 5.0))
(tu-eqf "ssg-tt-versetzt/y" '(0.0 2.0 0.0) (ssg-tt-versetzt '(0.0 0.0 0.0) (/ pi 2.0) 2.0))
(tu-eqf "ssg-tt-versetzt/2d" '(1.0 4.0 0.0) (ssg-tt-versetzt '(1.0 1.0) (/ pi 2.0) 3.0))
)
)
)
(defun c:TEST_UNIT ( / out-dir report)
(tu-reset)
(princ "\n================================================================")
@@ -1589,7 +1660,8 @@
(foreach fn '("tu-tests-core" "tu-tests-lang" "tu-tests-id" "tu-tests-vfcore"
"tu-tests-export" "tu-tests-gf" "tu-tests-omni" "tu-tests-kreisel"
"tu-tests-sepliste" "tu-tests-json" "tu-tests-geruest"
"tu-tests-sepscan" "tu-tests-vfl-segs" "tu-tests-vfl-abbruch")
"tu-tests-sepscan" "tu-tests-vfl-segs" "tu-tests-vfl-abbruch"
"tu-tests-werkzeuge")
(tu-run-block fn))
(princ "\n\n----------------------------------------------------------------")