---- [http://web.tiscali.it/marcomaggi/images/canvas_polygon_buttons.png] Image link appears broken on July 8, 2012. ---- [MM] Strange thing: if I move the pointer just above the text on a button and click the event is delivered (I have verified that uwp_cb_action_press is invoked) but then nothing happens: the button is not pressed. There is a small rectangle area just above the text item that shows this behaviour: if I move the pointer a few pixel above or below everything works. I was not able to reproduce the behaviour with a script that just displayes a canvas with a polygon and a word of text in it, so the bug must be in my code. ---- [MM] If someone is able to suggest a way to draw an outer polygon to mimic the highlight border when the focus in in, let me know thank you. ---- ====== # canvas_polygon_button.tcl -- # # Part of: Useless Widgets Packages # Contents: test canvas buttons # Date: Wed Dec 22, 2004 # Credits: Gerard Sookahet has put the superformula on the TCL'ers Wiki # # Abstract # # It should support all the common button operations: # # * when the pointer enters the button is hilighted; # * when the button is clicked it is pressed; # * when the pointer leaves the button is de-hilighted # and raised (if pressed); # * when the button is unclicked the button is raised # (if pressed) and the command invoked (if the button # is pressed); # * if focus comes in the text is underlined; # * if the focus goes out the text is deunderlined; # * if the "Return" key is pressed while the focus is in # the button is pressed and then depressed after 100 ms, # and the command invoked. # # Copyright (c) 2004 Marco Maggi # # The author hereby grant permission to use, copy, modify, distribute, # and license this software and its documentation for any purpose, # provided that existing copyright notices are retained in all copies # and that this notice is included verbatim in any distributions. No # written agreement, license, or royalty fee is required for any of the # authorized uses. Modifications to this software may be copyrighted by # their authors and need not follow the licensing terms described here, # provided that the new terms are clearly indicated on the first page of # each file where they apply. # # IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY PARTY # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES # ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY # DERIVATIVES THEREOF, EVEN IF THE AUTHOR HAVE BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND # NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, # AND THE AUTHOR AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE # MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # # #page ## ------------------------------------------------------------ ## Setup. ## ------------------------------------------------------------ package require Tcl 8.4 package require Tk 8.4 #page ## ------------------------------------------------------------ ## Widget options. ## ------------------------------------------------------------ option add *borderWidth 1 option add *Cb.relief flat option add *Cb.canvas.relief flat option add *Cb.borderWidth 2 option add *Cb*highlightThickness 0 # this is the default light gray option add *Cb.background "\#d9d9d9" option add *Cb.bbground "\#d9d9d9" # bisque see the "colors" man page or "/usr/X11R6/lib/X11/rgb.txt" option add *Cb.activebbground bisque option add *Cb.foreground black option add *Cb.pressedbordercolor {dark gray} option add *Cb.width 100 option add *Cb.height 100 option add *Cb.takeFocus 1 option add *Cb.text Text option add *Cb.font {-weight bold -family Helvetica -size 12} #page ## ------------------------------------------------------------ ## Main. ## ------------------------------------------------------------ proc main {} { global exit_trigger wm title . "Testing canvas buttons" wm geometry . +100+100 set counter 0 set col -1 foreach {name num fraction} { a 3 -4 b 4 8 c 6 1 d 12 1 e 50 1 } { uwp_cb_build .$name [polygon_regular_coords $num 0.8 $fraction] \ button_command grid .$name -row 0 -column [incr col] } set col -1 foreach {name num} { m 3 n 4 o 6 p 12 q 20 } { uwp_cb_build .$name [polygon_star_coords $num] button_command grid .$name -row 1 -column [incr col] } set col -1 # parms: a b m n1 n2 n3 foreach {name parms} { r {0.7 0.9 6.0 1.0 2.0 1.4} s {0.9 0.7 12.0 1.5 2.0 7.5} t {0.9 0.7 10.0 0.9 1.7 1.1} } { uwp_cb_build .$name [eval superformula $parms] button_command grid .$name -row 2 -column [incr col] } grid \ [label .l -text 0 -width 5 -background \#ffffff] \ [button .quit -text Exit -command main_exit] focus .quit bind .quit main_exit interp alias {} main_exit {} set exit_trigger 1 vwait exit_trigger exit } proc button_command {} { .l configure -text [expr {[.l cget -text]+1}] } #page proc polygon_regular_coords { num radius {fraction 1.0} } { for {set i 0} {$i < $num} {incr i} { set angle [expr {6.28318530718/double($fraction)+ (6.28318530718*double($i)/double($num))}] lappend coords \ [expr {double($radius)*cos($angle)}] \ [expr {double($radius)*sin($angle)}] } return $coords } proc polygon_star_coords { num } { set fraction [expr {double($num)*2.0}] foreach {x1 y1} [polygon_regular_coords $num 0.9] \ {x2 y2} [polygon_regular_coords $num 0.6 $fraction] { lappend result $x1 $y1 $x2 $y2 } return $result } proc superformula { a b m n1 n2 n3 } { set num 50 for {set i 0} {$i < $num} {incr i} { set theta [expr {double($i)*6.28318530718/double($num)}] set rho \ [expr { pow(pow(abs(cos(0.25*double($m)*double($theta))/double($a)), double($n2))+ pow(abs(sin(0.25*double($m)*double($theta))/double($b)), double($n2)), (-1/double($n1))) }] lappend result [expr {$rho*cos($theta)}] [expr {$rho*sin($theta)}] } return $result } #page proc uwp_op_array { widget varName } { uplevel [list array set $varName { a b }] uplevel [list trace add variable $varName read [list uwp_op_get $widget]] uplevel [list trace add variable $varName write [list uwp_op_set $widget]] } proc uwp_op_get { widget name1 name2 op } { upvar $name1 options set options($name2) [option get $widget $name2 {}] } proc uwp_op_set { widget name1 name2 op } { upvar $name1 options option add *[string trimleft $widget .].$name2 $options($name2) } #page proc uwp_cb_build { widget coords {command {}} } { global uwp_data uwp_op_array $widget options frame $widget -class Cb canvas [set c $widget.canvas] -background $options(background) \ -width $options(width) -height $options(height) grid $c set width [$c cget -width] set height [$c cget -height] foreach {x y} $coords { lappend border_coords \ [expr {int((double($x)+1.0)*double($width)*0.5)}] \ [expr {int((double($y)+1.0)*double($height)*0.5)}] } array set uwp_data \ [list $widget:border_coords $border_coords $widget:pressed no] $c create polygon $border_coords -tags {Clickable Button} \ -fill $options(bbground) $c create text [expr {int($width/2)}] [expr {int($height/2)}] \ -text $options(text) -font $options(font) \ -fill $options(foreground) -tags {Clickable Text} uwp_p_cb_draw_released_border $widget bind $widget [list uwp_p_cb_destroy $widget] bind $widget [list uwp_cb_event_focus yes $widget] bind $widget [list uwp_cb_event_focus no $widget] bind $widget [list uwp_cb_event_return $widget] $c bind Clickable [list uwp_cb_event_release $widget] $c bind Clickable [list uwp_cb_event_press $widget] $c bind Clickable [list uwp_cb_event_enter $widget] $c bind Clickable [list uwp_cb_event_leave $widget] uwp_cb_command $widget $command return $widget } proc uwp_p_cb_destroy { widget } { global uwp_data array unset uwp_data $widget:* } #page proc uwp_p_cb_draw_border { pressed widget } { global uwp_data uwp_op_array $widget options set coords $uwp_data($widget:border_coords) set coords1 [concat [lrange $coords 2 end] [lrange $coords 0 1]] foreach {x1 y1} $coords {x2 y2} $coords1 { set d [expr {(-double($y2-$y1)+double($x2-$x1))/ sqrt(pow(double($y2-$y1),2.0)+pow(double($x2-$x1),2.0))}] set level [expr {180+int(50.0*$d)}] if { $pressed } { if { $level < 200 } { set color $options(background) } else { set color $options(pressedbordercolor) } } else { set color [format "\#%x%x%x" $level $level $level] } $widget.canvas create line $x1 $y1 $x2 $y2 \ -fill $color -tags Border -width $options(borderWidth) } } interp alias {} uwp_p_cb_draw_pressed_border {} uwp_p_cb_draw_border yes interp alias {} uwp_p_cb_draw_released_border {} uwp_p_cb_draw_border no proc deg2rad { angle } { expr {double($angle)*57.2957795131} } #page proc uwp_cb_command { widget {command {}} } { global uwp_data set uwp_data($widget:command) $command } proc uwp_cb_invoke { widget } { upvar \#0 uwp_data($widget:command) cmd if { [string length $cmd] } { uplevel \#0 $cmd } } proc uwp_cb_event_press { widget } { uwp_cb_action_press $widget } proc uwp_cb_event_release { widget } { upvar \#0 uwp_data($widget:pressed) pressed if { $pressed } { after 0 [list uwp_cb_invoke $widget] } uwp_cb_action_release $widget } proc uwp_cb_event_enter { widget } { uwp_cb_action_state_active $widget } proc uwp_cb_event_leave { widget } { uwp_cb_action_state_normal $widget uwp_cb_action_release $widget } proc uwp_cb_event_focus { mode widget } { $widget.canvas itemconfigure Text \ -font [concat [$widget.canvas itemcget Text -font] [list -underline $mode]] } proc uwp_cb_event_return { widget } { uwp_cb_event_press $widget after 100 [list uwp_cb_event_release $widget] } #page proc uwp_cb_action_state_active { widget } { uwp_op_array $widget options $widget.canvas itemconfigure Button -fill $options(activebbground) } proc uwp_cb_action_state_normal { widget } { uwp_op_array $widget options $widget.canvas itemconfigure Button -fill $options(bbground) } proc uwp_cb_action_press { widget } { upvar \#0 uwp_data($widget:pressed) pressed if { ! $pressed } { uwp_p_cb_draw_pressed_border $widget $widget.canvas move Text 2 2 set pressed yes } } proc uwp_cb_action_release { widget } { upvar \#0 uwp_data($widget:pressed) pressed if { $pressed } { uwp_p_cb_draw_released_border $widget $widget.canvas move Text -2 -2 set pressed no } } #page ## ------------------------------------------------------------ ## Let's go. ## ------------------------------------------------------------ main ### end of file # Local Variables: # mode: tcl # End: ====== <> Graphics