;;;; ;;;; Copyright © 1993-1996 Erick Gallesio - I3S-CNRS/ESSI ;;;; ;;;; Permission to use, copy, and/or distribute this software and its ;;;; documentation for any purpose and without fee is hereby granted, provided ;;;; that both the above copyright notice and this permission notice appear in ;;;; all copies and derived works. Fees for distribution or use of this ;;;; software or derived works may only be charged with express written ;;;; permission of the copyright holder. ;;;; This software is provided ``as is'' without express or implied warranty. ;;;; ;;;; This software is a derivative work of other copyrighted softwares; the ;;;; copyright notices of these softwares are placed in the file COPYRIGHTS ;;;; ;;;; ;;;; Author: Erick Gallesio [eg@unice.fr] ;;;; Creation date: 8-Sep-1995 11:37 ;;;; Last file update: 22-Feb-1996 11:19 ;;;; ;; Tk:tear-off-menu -- ;; Given the name of a menu, this procedure creates a torn-off menu ;; that is identical to the given menu (including nested submenus). ;; The new torn-off menu exists as a toplevel window managed by the ;; window manager. The return value is the name of the new menu. ;; ;; Arguments: ;; w - The menu to be torn-off (duplicated). (define (Tk:tear-off-menu w) (define (Tk:menu-dup src dst) ;; duplicate src menu into dst (let ((args '())) (for-each (lambda (option) (unless (= (length option) 2) (set! args `(,(car option) ,(list-ref option 4) ,@args)))) (src 'configure)) (set! dst (apply Tk:menu dst args)) (let ((last (src 'index "last"))) (unless (equal? last "none") (let loop ((i (if (tk-get src :tearoff) 1 0))) (when (<= i last) (let ((args '()) (type (src 'type i))) (for-each (lambda (option) (set! args `(,(car option) ,(list-ref option 4) ,@args))) (src 'entryconfigure i)) (apply dst 'add type args) (if (equal? type "cascade") (let* ((name (format #f "~A.m~A" (widget-name dst) i)) (m2 (src 'entrycget i :menu))) (if m2 (begin (Tk:menu-dup m2 name) (dst 'entryconfigure i :menu name)) (dst 'entryconfigure i :menu "")))) (loop (+ i 1))))))) ;; Duplicate the binding tags and bindings from the source menu. ; ; regsub -all . $src {\\&} quotedSrc ; regsub -all . $dst {\\&} quotedDst ; regsub -all $quotedSrc [bindtags $src] $dst x ; bindtags $dst $x ; foreach event [bind $src] { ; regsub -all $quotedSrc [bind $src $event] $dst x ; bind $dst $event $x ; } ; ; Is it really useful? Should we duplicate bindings on the copy? ; Furthermore, most of the time this code should do nothing (even if ; necessary for completude). ; Eventually translate this Tcl code in STk but don't use regexp ; since they could not be compiled for STk ;; Return dst as result dst)) ;;******** Start of Tk:tear-off-menu ;; Find a unique name to use for the torn-off menu. Find the first ;; ancestor of w that is a toplevel but not a menu, and use this as ;; the parent of the new menu. This guarantees that the torn off ;; menu will be on the same screen as the original menu. By making ;; it a child of the ancestor, rather than a child of the menu, it ;; can continue to live even if the menu is deleted; it will go ;; away when the toplevel goes away. (let ((parent [winfo 'parent w])) (while (or (not (equal? parent [winfo 'toplevel parent])) (equal? (winfo 'class parent) "Menu")) (set! parent [winfo 'parent parent])) (let ((menu (Tk:menu-dup w (format #f "~A.~A" (if (equal? parent *root*) "" (widget-name parent)) (gensym "tear__off"))))) (tk-set! menu :transient #f) ;; Pick a title for the new menu by looking at the parent of the ;; original: if the parent is a menu, then use the text of the active ;; entry. If it's a menubutton then use its text. (set! parent [winfo 'parent w]) (wm 'title menu (cond ((string=? [winfo 'class parent] "Menubutton") (tk-get parent :text)) ((string=? [winfo 'class parent] "Menu") (parent 'entrycget "active" :label)) (ELSE "Menu"))) (tk-set! menu :tearoff #f) (menu 'post [winfo 'x w] [winfo 'y w]) ;; Set tk::focus on entry: otherwise the focus will get lost ;; after keyboard invocation of a sub-menu (it will stay on the ;; submenu). (bind menu "" (lambda (|W|) (set! tk::focus |W|))) ;; If there is a :tearoffcommand option for the menu, invoke it ;; now. (let ((cmd (tk-get w :tearoffcommand))) (unless (equal? cmd "") (cmd w menu))))))