Version 5 of Pie menu

Updated 2007-06-22 17:58:09 by dzach

a circular menu, that appears where the mouse button is pressed

see wikipedia [L1 ]

Pie Menues for All at [L2 ] includes a demonstration in tcl/tk


GS (060203) Also known as compass menu in some 3D software [L3 ].


dzach 2007-6-22 : Here is my try for some pie menus on a canvas:

 proc piemenu {W args} {
         # draws a pie menu on canvas W
         # array angles contains pairs of
         #        nrbuttons {{button center angle} {button angle extent}}
         # button 0 is always the central one  

         array set angles {
                 1 {} 
                 2 {0 359.999} 
                 3 {180 180 0 180} 
                 4 {90 120 210 120 330 120} 
                 5 {90 90 180 90 0 90 270 90} 
                  6 {90 60 150 60 30 60 225 90 -45 90}
                 7 {90 60 150 60 30 60 270 60 -150 60 -30 60}
         }
         array set opt {
                 -r 100 
                 -nrbuttons 2 
                 -width 4 
                 -fill #eeeeee 
                 -outline #888888 
                 -activefill #f0ffff
                 -activeoutline #80ffff
                 -selectfill #ffcfcf 
                 -selectoutline #ff8080 
                 -textfill #444444
         }
         array set opt $args
         if {![info exists opt(-x)]} {
                 set opt(-x) [expr {$opt(-r) + $opt(-width)/2.0}]
         }
         if {![info exists opt(-y)]} {
                 set opt(-y) [expr {$opt(-r) + $opt(-width)/2.0}]
         } 

         set r 0.375
         set x0 [expr {$opt(-x) - $opt(-r)}]
         set y0 [expr {$opt(-y) - $opt(-r)}]
         set cnt 1
         foreach {angle extent} $angles($opt(-nrbuttons)) {

                 set start [expr {$angle - $extent / 2.0}]
                 $W create arc $x0 $y0 [expr {$x0 + 2 * $opt(-r)}] [expr {$y0 + 2 * $opt(-r)}] \
                         -tags [list __pm$cnt __pm] \
                         -extent $extent -start $start \
                         -width $opt(-width) \
                         -fill [expr {[info exists opt(-fill$cnt)] ? $opt(-fill$cnt) : $opt(-fill)}] \
                         -outline [expr {[info exists opt(-outline$cnt)] ? $opt(-outline$cnt) : $opt(-outline)}]

                 $W bind __pm$cnt <Button-1> "%W itemconfig \[%W find closest %x %y] -fill $opt(-selectfill)"
                 $W bind __pm$cnt <ButtonRelease-1> "%W itemconfig \[%W find closest %x %y] -fill $opt(-fill)"

                 $W create text \
                         [expr {$opt(-x) + (1 - $r) * $opt(-r) * cos(0.017453292519943294892 * $angle)}] \
                         [expr {$opt(-y) - (1 - $r) * $opt(-r) * sin(0.017453292519943294892 * $angle)}] \
                         -tags [list __pmt$cnt __pm] \
                         -text [expr {[info exists opt(-text$cnt)] ? $opt(-text$cnt) : "__pm$cnt"}] \
                         -font {Helvetica -12 bold} \
                         -fill [expr {[info exists opt(-textfill$cnt)] ? $opt(-textfill$cnt) : $opt(-textfill)}]
                 incr cnt
         }
         set x0 [expr {$opt(-x) - $r * $opt(-r)}]
         set y0 [expr {$opt(-y) - $r * $opt(-r)}]

         $W create oval $x0 $y0 [expr {$x0 + 2 * $r * $opt(-r)}] [expr {$y0 + 2 * $r * $opt(-r)}] \
                 -tags [list __pm0 __pm] \
                 -width $opt(-width) \
                 -fill [expr {[info exists opt(-fill0)] ? $opt(-fill0) : $opt(-fill)}] \
                 -outline [expr {[info exists opt(-outline0)] ? $opt(-outline0) : $opt(-outline)}]

         $W bind __pm0 <Button-1> "%W itemconfig \[%W find closest %x %y] -fill $opt(-selectfill)"
         $W bind __pm0 <ButtonRelease-1> "%W itemconfig \[%W find closest %x %y] -fill $opt(-fill)" 

         $W create text $opt(-x) $opt(-y) \
                 -tags [list __pmt0 __pm] \
                 -text [expr {[info exists opt(-text0)] ? $opt(-text0) : "__pm0"}] \
                 -font {Helvetica -12 bold} \
                 -fill [expr {[info exists opt(-textfill0)] ? $opt(-textfill0) : $opt(-textfill)}]
 }
 #
 # test code
 #
 catch {destroy .c}
 pack [canvas .c -bg white -width 400 -height 400] -fill both -expand 1
 .c create text 10 10 -text "Click Button-1 to cycle pie menu, Button-3 to hide" -anchor nw
 set cnt 0
 bind .c <Button-1> "
         %W delete __pm;
         piemenu %W -x %x -y %y \
         -nrbuttons \[expr {\$cnt %% 7 + 1}] \
         -r 75 \
         -fill0 #ffffff \
         -text0 Ok \
         -text1 test \
         -text2 toast \
         -text3 taste \
         -text4 toes \
         -text5 tease \
         -text6 tees \
         -width 2 \
         ;incr cnt
         "
 bind .c <Button-3> { %W delete __pm; set cnt 0 }

An Firefox extension for replacing the context menu with a pie menu:

http://www.radialthinking.de/radialcontext/ --- Category GUI | Category Widget