This (sub)function is part of a larger appie I'm currently working on (not sure how I'm gonna name the larger app yet , for now called it RlxBlockSync but also entertaining the idea to call RFD, redefine for dummies )
Anyways, this sub dynamically creates a dialog and takes 'commatized' strings for input. Few years ago I wrote Tokkie, this basically does the same , just a little different and with less code. I was inspired by a similar function master L created and later Grrr made something like that.
The reason I use commatized / csv strings is so I can save the output of this function as a string in the registry. Added little test function which generates 3 list boxes but you can have as many LB's as you like, the only limitations are your imagination and the width of your monitor. I hope by analyzing the test function (c:t1) you understand how you can use this function.
; multiple input listbox function : mlist = ( ( description1 (labels1) (defaults1) ) ...)
(defun milf ( mlist / get_lb_width commatize de-commatize _ufo toggle fn fp dcl lb-width old-props new-props plist tmp out)
; get max strlen from list arguments for milf
(defun get_lb_width (l) (apply 'max (mapcar 'strlen (apply 'append (mapcar 'de-commatize (mapcar 'cadr l))))))
; (commatize '("a" "b" "c")) -> "a,b,c"
(defun commatize (l) (apply 'strcat (cdr (apply 'append (mapcar '(lambda (x) (list "," x)) l)))))
; (de-commatize "a,b,c") -> ("a" "b" "c")
(defun de-commatize (s / p)(if (setq p (vl-string-search "," s))(cons (substr s 1 p)(de-commatize (substr s (+ p 2))))(list s)))
; use filter on : (_ufo "*" '("door" "table" "floor")) (_ufo "o" '("door" "table" "floor"))
(defun _ufo ( f l ) (if (and (= (type f) 'STR) (/= f ""))
(vl-remove-if '(lambda (s)(not (or (eq f "*") (vl-string-search (strcase f)(strcase s))))) l)))
; adds / removes [0] or [X] before each item in listboxes
(defun toggle (k v / lst r s)
(if (eq (substr (setq r (nth (atoi v) (setq lst (cdr (assoc k plist))))) 2 1) "X") (setq s "[O] ") (setq s "[X] "))
(setq plist (subst (cons k (setq lst (subst (strcat s (substr r 5)) r lst))) (assoc k plist) plist))
(start_list k)(mapcar 'add_list lst)(end_list)(set_tile k v))
; calculated width of list boxes by finding longest string
(setq lb-width (+ (get_lb_width mlist) 5))
(if (not (setq fp (open (setq fn (vl-filename-mktemp ".dcl")) "w")))
(princ "\nUnable to create temporary dcl file")
(progn
(write-line "milf:dialog {label=\"Multiple Input Listbox Function (RLX 5/'20)\";:row {" fp)
(setq lb 0)
(foreach item mlist (write-line (strcat ":column {label=\"" (car item)
"\";:list_box{height=16;width=" (itoa lb-width) ";key=\"lb" (itoa (setq lb (1+ lb))) "\";}}") fp))
(write-line "}ok_cancel;}" fp)(if fp (progn (close fp)(gc)))
(if (not (and (< 0 (setq dcl (load_dialog fn))) (new_dialog "milf" dcl)))
(princ "\nUnable to start dialog milf")
(progn
(setq lb 0)
(foreach item mlist
(setq old-props (de-commatize (cadr item)) new-props (de-commatize (caddr item)))
(setq l (mapcar '(lambda (x)(if (member x new-props)(strcat "[X] " x)(strcat "[O] " x))) old-props))
(setq lb-id (strcat "lb" (itoa (setq lb (1+ lb)))) plist (cons (cons lb-id l) plist))
(start_list lb-id) (mapcar 'add_list l) (end_list)
(action_tile (strcat "lb" (itoa lb)) "(toggle $key $value)")
)
(action_tile "accept" "(done_dialog 1)")
(action_tile "cancel" "(done_dialog 0)")
(setq drv (start_dialog)) (unload_dialog dcl)(vl-file-delete fn)
)
)
)
)
(if (= drv 1) (mapcar '(lambda (x)(commatize (mapcar '(lambda (y)(substr y 5)) x)))
(mapcar '(lambda (x)(_ufo "[X]" x))(mapcar 'cdr (reverse plist)))) nil)
)
(defun c:t1 ( / result-list animals breakfast music)
(setq animals "Aardvark,Baboon,Camel,Dragons,Easterbunny,Firebird,Godzilla,Hobbit,Idiot,Phoenix")
(setq breakfast "Anna Nicole,Beyoncé Knowles,Carmen Electra,Daenerys Targaryen,Ella Enchanted,Gal Gadot,Sophie Turner")
(setq music "Andrea Bocelli,Electric Light Orchestra,Earth Wind & Fire,George Michael,Lara Fabian,Queen")
(setq result-list
(milf
(list
(list "Animals" animals "Dragons,Phoenix")
(list "Breakfast" breakfast "Gal Gadot,Sophie Turner")
(list "Music" music "Electric Light Orchestra,Lara Fabian")
;;; add as many list as you want limited only by the size of the screen
)
)
)
(princ "\n\nYou made the following selections : ")
(mapcar '(lambda (label value) (princ (strcat "\n\n" label "\nvalue : " value)))
'("Animals :" "Breakfast :" "Music :" ) result-list)
(princ "\n\n")
(princ)
)
I can show you how other app looks , but that's not finished yet (if ever) so will get back to that later
Awell... hope I didn't forget any sub functions that are allways loaded automatically on my own pc (autoload & forget) but if so let me know (wouldn't be the first time I forgot something and probably not the last time)
happy coding