/usr/share/tcltk/tklib0.5/tkpiechart/perilabel.tcl is in tklib 0.5-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | # copyright (C) 1995-2004 Jean-Luc Fontaine (mailto:jfontain@free.fr)
package require Tk 8.3
package require stooop
::stooop::class piePeripheralLabeler {
variable PI 3.14159265358979323846
proc piePeripheralLabeler {this canvas args} pieLabeler {$canvas $args}\
switched {$args} {
switched::complete $this
::set ($this,array) [::stooop::new canvasLabelsArray $canvas\
-justify $switched::($this,-justify)\
]
::set ($this,valueWidth) [font measure\
$switched::($this,-smallfont) $switched::($this,-widestvaluetext)\
]
::set ($this,valueHeight)\
[font metrics $switched::($this,-smallfont) -ascent]
}
proc ~piePeripheralLabeler {this} {
::stooop::delete $($this,array)
# delete remaining items (should be in pieLabeler destructor)
$pieLabeler::($this,canvas) delete pieLabeler($this)
}
proc options {this} {
# bullet width, font and justify options are used when creating a new
# canvas label
# justify option is used for both the labels array and the labels
return [list\
[list -bulletwidth 20 20]\
[list -font\
$pieLabeler::(default,font) $pieLabeler::(default,font)\
]\
[list -justify left left]\
[list -offset 5 5]\
[list -smallfont {Helvetica -10} {Helvetica -10}]\
[list -widestvaluetext 0.00 0.00]\
]
}
foreach option {\
-bulletwidth -font -justify -offset -smallfont -widestvaluetext\
} { ;# no dynamic options allowed
proc set$option {this value} "
if {\$switched::(\$this,complete)} {
error {option $option cannot be set dynamically}
}
"
}
proc set-smallfont {this value} {
if {$switched::($this,complete)} {
error {option -smallfont cannot be set dynamically}
}
}
proc new {this slice args} {
# variable arguments are for the created canvas label object
::set canvas $pieLabeler::($this,canvas)
::set text [$canvas create text 0 0\
-font $switched::($this,-smallfont) -tags pieLabeler($this)\
] ;# create value label
::set label [eval ::stooop::new canvasLabel\
$pieLabeler::($this,canvas) $args\
[list\
-justify $switched::($this,-justify)\
-bulletwidth $switched::($this,-bulletwidth)\
-font $switched::($this,-font) -selectrelief sunken\
]\
]
canvasLabelsArray::manage $($this,array) $label
$canvas addtag pieLabeler($this)\
withtag canvasLabelsArray($($this,array)) ;# refresh our tags
# value text item is the only one to update
::set ($this,textItem,$label) $text
::set ($this,slice,$label) $slice
::set ($this,selected,$label) 0
return $label
}
proc anglePosition {degrees} {
# quadrant specific index with added value for exact quarters
return [expr {(2 * ($degrees / 90)) + (($degrees % 90) != 0)}]
}
::set index 0 ;# build angle position / value label anchor mapping array
foreach anchor {w sw s se e ne n nw} {
::set (anchor,[anglePosition [expr {$index * 45}]]) $anchor
incr index
}
unset index anchor
proc set {this label value} {
::set text $($this,textItem,$label)
position $this $text $($this,slice,$label)
$pieLabeler::($this,canvas) itemconfigure $text -text $value
}
proc label {this label args} {
if {[llength $args] == 0} {
return [switched::cget $label -text]
} else {
switched::configure $label -text [lindex $args 0]
}
}
proc labelBackground {this label args} {
if {[llength $args] == 0} {
return [switched::cget $label -background]
} else {
switched::configure $label -background [lindex $args 0]
}
}
proc labelTextBackground {this label args} {
if {[llength $args] == 0} {
return [switched::cget $label -textbackground]
} else {
switched::configure $label -textbackground [lindex $args 0]
}
}
proc position {this text slice} {
# place the value text item next to the outter border of the
# corresponding slice
variable PI
# retrieve current slice position and dimensions
slice::data $slice data
# calculate text closest point coordinates in normal coordinates system
# (y increasing in north direction)
::set midAngle [expr {$data(start) + ($data(extent) / 2.0)}]
::set radians [expr {$midAngle * $PI / 180}]
::set x [expr {\
($data(xRadius) + $switched::($this,-offset)) * cos($radians)\
}]
::set y [expr {\
($data(yRadius) + $switched::($this,-offset)) * sin($radians)\
}]
::set angle [expr {round($midAngle) % 360}]
if {$angle > 180} {
::set y [expr {$y - $data(height)}] ;# account for pie thickness
}
::set canvas $pieLabeler::($this,canvas)
# now transform coordinates according to canvas coordinates system
::set coordinates [$canvas coords $text]
$canvas move $text\
[expr {$data(xCenter) + $x - [lindex $coordinates 0]}]\
[expr {$data(yCenter) - $y - [lindex $coordinates 1]}]
# finally set anchor according to which point of the text is closest to
# pie graphics
$canvas itemconfigure $text -anchor $(anchor,[anglePosition $angle])
}
proc delete {this label} {
canvasLabelsArray::delete $($this,array) $label
$pieLabeler::($this,canvas) delete $($this,textItem,$label)
unset\
($this,textItem,$label) ($this,slice,$label) ($this,selected,$label)
# finally reposition the remaining value text items next to their slices
foreach label [canvasLabelsArray::labels $($this,array)] {
position $this $($this,textItem,$label) $($this,slice,$label)
}
}
proc selectState {this label {selected {}}} {
if {[string length $selected] == 0} {
# return current state if no argument
return $($this,selected,$label)
}
switched::configure $label -select $selected
::set ($this,selected,$label) $selected
}
proc update {this left top right bottom} {
# arguments: whole pie coordinates, includings labeler labels
::set canvas $pieLabeler::($this,canvas)
# first reposition labels array below pie graphics
::set array $($this,array)
::set width [expr {$right - $left}]
if {$width != [switched::cget $array -width]} {
switched::configure $array -width $width ;# fit pie width
} else {
canvasLabelsArray::update $array
}
foreach {x y} [$canvas coords canvasLabelsArray($array)] {}
$canvas move canvasLabelsArray($array) [expr {$left - $x}]\
[expr {$bottom - [canvasLabelsArray::height $array] - $y}]
}
proc updateSlices {this left top right bottom} {
foreach label [canvasLabelsArray::labels $($this,array)] {
# position peripheral labels
position $this $($this,textItem,$label) $($this,slice,$label)
}
}
proc room {this arrayName} {
upvar 1 $arrayName data
::set data(left)\
[expr {$($this,valueWidth) + $switched::($this,-offset)}]
::set data(right) $data(left)
::set data(top)\
[expr {$switched::($this,-offset) + $($this,valueHeight)}]
::set box\
[$pieLabeler::($this,canvas) bbox canvasLabelsArray($($this,array))]
if {[llength $box] == 0} { ;# no labels yet
::set data(bottom) $data(top)
} else { ;# room taken by all labels including offset
::set data(bottom)\
[expr {$data(top) + [lindex $box 3] - [lindex $box 1]}]
}
}
}
|