#| Les menus virtuels sur le bitmap virtuel |# (setq #:sys-package:colon '#:menu:llmenu) (defstruct #:menu:llmenu name invertedx invertedy (itemlists ())) (defstruct itemlist name active items) (de itemlist (name items) (let ((res (#:itemlist:make))) (#:itemlist:name res name) (#:itemlist:active res active) (#:itemlist:items res items) res)) (defstruct item name active value) (de item (name active value) (let ((res (#:item:make))) (#:item:name res name) (#:item:active res active) (#:item:value res value) res)) (de #:bitmap:create-menu (menu) (let ((new (:make))) (bltvector new 0 menu (vlength menu)) new)) (de :kill-menu (menu)) (de :activate-menu (menu x y) (:draw-menu menu x y) (:follow-mouse menu) (let (x y il item) (when (and (setq x (:invertedx menu)) (setq y (:invertedy menu)) (ge x 0) (ge y 0) (setq il (nth x (:itemlists menu))) il (setq item (nth y (#:itemlist:items il))) item (neq 0 (#:item:active item))) (#:item:value item)))) (de :height (menu) (mul (height-space) (apply 'max (cons 0 (mapcar (lambda (il) (length (#:itemlist:items il))) (:itemlists menu)))))) (de width-string (s) (width-substring s 0 (slen s))) (de #:itemlist:width (il) (ifn (consp (#:itemlist:items il)) 0 (apply 'max (mapcar (lambda (it) (width-string (#:item:name it))) (#:itemlist:items il))))) (de :width (menu) (apply '+ (mapcar '#:itemlist:width (:itemlists menu)))) (de :draw-menu (menu x y) (let* ((w (:width menu)) (h (:height menu)) (window (create-window 'window (sub x (div w 2)) y w h (:name menu) 1 1)) (x (x-base-space)) (y (y-base-space))) (#:menu:extend menu window) (with ((current-window window)) (mapc (lambda (il) (mapc (lambda (it) (draw-string x y (#:item:name it)) (setq y (+ y (height-space)))) (#:itemlist:items il)) (setq y (y-base-space)) (setq x (add x (#:itemlist:width il)))) (:itemlists menu))))) (de :find-list (menu x) (:find-list1 (:itemlists menu) x 0)) (de :find-list1 (ils x res) (cond ((lt x 0) ()) ((null ils) ()) ((lt x (#:itemlist:width (car ils))) res) (t (:find-list1 (cdr ils) (sub x (#:itemlist:width (car ils))) (add1 res))))) (de :itemlist-x (menu x) (:itemlist-x1 x (:itemlists menu))) (de :itemlist-x1 (x ils) (if (eq x 0) 0 (add (#:itemlist:width (car ils)) (:itemlist-x1 (sub1 x) (cdr ils))))) (de :invert-item (menu x y) (let (il item) (when (and x y (setq il (nth x (:itemlists menu))) (neq 0 (#:itemlist:active il)) (setq item (nth y (#:itemlist:items il))) (neq 0 (#:item:active item))) (let ((rx (:itemlist-x menu x)) (ry (mul y (height-space))) (rw (#:itemlist:width il)) (rh (height-space))) (fill-rectangle rx ry rw rh))))) (unless (boundp ':local-read-mouse:x) (defvar :local-read-mouse:x 0) (defvar :local-read-mouse:y 0) (defvar :local-read-mouse:event #:event:#[0 0 0 0 0 0 0 0 0])) (de :local-read-mouse () (read-mouse :local-read-mouse:event) (map-window (current-window) (#:event:gx :local-read-mouse:event) (#:event:gy :local-read-mouse:event) ':local-read-mouse:x ':local-read-mouse:y) (#:event:window :local-read-mouse:event ()) (#:event:x :local-read-mouse:event :local-read-mouse:x) (#:event:y :local-read-mouse:event :local-read-mouse:y) :local-read-mouse:event) (de :follow-mouse (menu) (with ((current-window (#:menu:extend menu))) (with ((current-mode 6) (current-pattern 1)) (let ((ix ()) (iy ()) nx ny event) (ungrab-event) (while (progn (setq event (:local-read-mouse)) (neq 0 (#:event:detail event))) (setq ny (div (#:event:y event) (height-space)) nx (:find-list menu (#:event:x event))) (when (or (neq nx ix) (neq ny iy)) (:invert-item menu ix iy) (setq ix nx iy ny) (:invert-item menu ix iy))) (:invertedx menu ix) (:invertedy menu iy)))) (kill-window (#:menu:extend menu)) (#:menu:extend menu ())) (de :menu-insert-item (menu choix index name active value) (let ((il (nth choix (:itemlists menu)))) (when il (#:itemlist:items il (insertnth index (#:itemlist:items il) (item name active value)))))) (de :menu-insert-item-list (menu choix name active) (:itemlists menu (insertnth choix (:itemlists menu) (itemlist name active)))) (de :menu-delete-item-list (menu choix) (:itemlists menu (deletenth choix (:itemlists menu)))) (de :menu-delete-item (menu choix index) (let ((il (nth choix (:itemlists menu)))) (when il (#:itemlist:items il (deletenth index (#:itemlist:items il)))))) (de :menu-modify-item-list (menu choix name active) (let ((il (nth choix (:itemlists menu)))) (when il (when name (#:itemlist:name il (string name))) (when active (#:itemlist:name il active))))) (de :menu-modify-item (menu choix index name active value) (let ((il (nth choix (:itemlists menu)))) (when il (let ((item (nth index il))) (when name (#:item:name item (string name))) (when active (#:item:name item active)) (when value (#:item:name item value)))))) (de deletenth (n l) (cond ((atom l) l) ((eq n 0) (cdr l)) (t (rplacd l (deletenth (sub1 n) (cdr l)))))) (de insertnth (n l i) (cond ((atom l) (cons i l)) ((eq n 0) (cons i l)) (t (rplacd l (insertnth (sub1 n) (cdr l) i)))))