While trying to re-implement ltktest with Celtk (+ Cells Ltk) I got
stumped by why Alt-Q worked for ltktest "classic" but not for me. Then I
noticed:
(bind *tk* "<Alt-q>" (lambda (event) (declare (ignore event)) (setf
*exit-mainloop* t)))
Not sure how well that scales to other menu items. Not an issue here,
but for one thing it fails to check whether the menu item being faked is
enabled. And at any rate it requires duplicating the code associated
with a menu item (tho here the menu item command was simply "exit").
Anyway...
I found something in one of my Tk books and did:
(defobserver accelerator :around ((self menu-entry-usable) new-value
old-value old-value-bound-p)
(call-next-method)
(with-integrity (:client '(:bind nil))
(when new-value
(tk-format-now "bind . ~a {~a invoke ~a}" new-value (path (upper
self menu)) (index self)))))
(forget most of that, but the idea is a general solution to menu accelerators via TCL "invoke").
Only tested for the same alt-q accelerator, but it could handle any
accelerator for any menu item. The TCL invoke, btw, does nothing if the
menu item is disabled.
Confession: since defobserver is an on-change handler, it really should
be looking for the odd case in which an accelerator got /removed/ (?!)
and then clear the binding.
ken