;;;; gtk-dialog.jl (require 'gui.gtk-2.gtk) ;; Each BUTTON is (TEXT . RETURNED-VALUE) (defun gtk-dialog (message &rest buttons) (let ((window (gtk-window-new 'toplevel)) (vbox (gtk-vbox-new nil 0)) (label (gtk-label-new message)) (bbox (gtk-hbutton-box-new))) (catch 'exit (unwind-protect (progn (gtk-container-border-width window 6) (gtk-signal-connect window "delete_event" (lambda () (throw 'exit nil))) (gtk-container-add window vbox) (gtk-box-pack-start vbox label) (gtk-box-pack-end vbox bbox) (mapc (lambda (cell) (let ((button (gtk-button-new-with-label (car cell)))) (GTK-WIDGET-SET-FLAGS button '(can-default)) (gtk-box-pack-start bbox button nil nil) (gtk-signal-connect button "clicked" (lambda () (throw 'exit (cdr cell)))))) buttons) (gtk-widget-show-all window) (gtk-main)) (gtk-widget-destroy window) ;; If I don't do this, the window isn't unmapped.. (while (> (gtk-events-pending) 0) (gtk-main-iteration)))))) (defun yes-or-no-p (question) (gtk-dialog question '("Yes" . t) '("No" . nil))) (defun y-or-n-p (q) (yes-or-no-p q)) (defun map-y-or-n-p (question inputs callback) (let ((all-t t)) (when (eq 'all-t (catch 'map (while inputs (let* ((q (if (stringp question) (format nil question (car inputs)) (question (car inputs)))) (a (gtk-dialog q '("Yes" . t) '("No" . nil) '("Yes to all" . all-t) '("Quit" . quit)))) (cond ((or (eq a 'all-t) (eq a 'quit)) (throw 'map a)) (a (callback (car inputs))) (t (setq all-t nil))) (setq inputs (cdr inputs)))))) ;; User answered with "!", so loop over all remaining inputs (while inputs (callback (car inputs)) (setq inputs (cdr inputs)))) all-t))