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 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
|
### Copyright (C) 1995-1997 Jesper K. Pedersen
### This program is free software; you can redistribute it and/or modify
### it under the terms of the GNU General Public License as published by
### the Free Software Foundation; either version 2 of the License, or
### (at your option) any later version.
###
### This program is distributed in the hope that it will be useful,
### but WITHOUT ANY WARRANTY; without even the implied warranty of
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
### GNU General Public License for more details.
###
### You should have received a copy of the GNU General Public License
### along with this program; if not, write to the Free Software
### Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
set __colorSet 0
######################################################################
# This function create a color scale window.
# The arguments are as follows:
# rgbList : a list of list with four elements: the
# color name the r,g,b values.
# defaultColor : the default color with a format as: #FF0FAA, or as
# a name from the rgbList.
# greyScaled : a boolean which indicate wether the
# element only shall display grey scaled colors
# The function will first return when the window disapear.
# The return value is a list were the first argument is a color, and the
# second determine wether the color should be edited in greyscaled.
# Iff a value is selected in the listbox, the name will be returned
# otherwise the RGB value will be returned.
# Iff the cancel button is pressed, the value given as argument will
# be returned.
######################################################################
proc ColorWidget {rgbList defaultColor greyScaled} {
global __greyscaled __colorMap __result __language
set labels "$__language(color,1) $__language(color,2) $__language(color,3)"
set __result ""
toplevel .scale
grabSet .scale
### calculate the defaultColor
if {[regexp {\#([0-9ABCDEF][0-9ABCDEF])([0-9ABCDEF][0-9ABCDEF])([0-9ABCDEF][0-9ABCDEF])$} $defaultColor all r g b] } {
set rgb [list [htoi $r] [htoi $g] [htoi $b]]
} else {
set defaultColor [string tolower $defaultColor]
set defaultColorIndex 0
set found 0
foreach color $rgbList {
if {[lindex $color 0] == $defaultColor} {
set rgb [lindex $color 1]
set found 1
break
}
incr defaultColorIndex
}
### This should only happend if a system save file says something about
### a font, which isn't installed on the system
if {!$found} {
set defaultColorIndex 0
set rgb [lindex [lindex $rgbList 0] 1]
}
}
### The test label with the actual color
### The double frame is needed otherwise the border will flicker
pack [frame .scale.frame -bd 4 -relief sunken] -pady 10
frame .scale.frame.test -width 300 -height 100
pack .scale.frame.test
bind .scale.frame.test <1> testClosestColor
### seperator line
frame .scale.line1 -height 0.1c -relief sunken -bd 1
pack .scale.line1 -fill x -expand 1 -pady 20
### Creating the scales
for {set i 0} {$i < 3} {incr i} {
pack [frame .scale.$i]
label .scale.$i.label -text "[lindex $labels $i]:\t"
scale .scale.$i.scale -from 0 -to 255 -orient horizontal -length 10c \
-command setColor
pack .scale.$i.label .scale.$i.scale -side left -anchor s
.scale.$i.scale set [lindex $rgb $i]
}
### Seperator line
frame .scale.line2 -height 0.1c -relief sunken -bd 1
pack .scale.line2 -fill x -expand 1 -pady 20
### The grey scale check button
checkbutton .scale.grey -text "Grey scaled" -variable __greyscaled \
-command {
if {$__greyscaled} {
bindtags .scale.lb.box None
bindtags .scale.lb.scroll None
.scale.lb.box configure -foreground grey -selectforeground black \
-selectbackground white
} else {
bindtags .scale.lb.box {Listbox .scale.lb.box .}
bindtags .scale.lb.scroll {Scrollbar .scale.lb.scroll}
.scale.lb.box configure -foreground black -selectforeground white \
-selectbackground black
}
}
pack .scale.grey -anchor w
### The listbox for the colors
pack [frame .scale.lb]
listbox .scale.lb.box -yscrollcommand ".scale.lb.scroll set" -width 45
scrollbar .scale.lb.scroll -command ".scale.lb.box yview"
pack .scale.lb.box .scale.lb.scroll -side left -fill y
### inserting elements into the listbox
set __colorMap $rgbList
foreach color $rgbList {
set name [lindex $color 0]
.scale.lb.box insert end $name
}
### setting the defaults
set __greyscaled $greyScaled
if {[info exists defaultColorIndex]} {
update
.scale.lb.box selection set $defaultColorIndex
.scale.lb.box yview $defaultColorIndex
}
### binding the scroll commands
bind .scale.lb.box <1> {
setColorAtPos [.scale.lb.box nearest %y]
}
bind .scale.lb.box <B1-Motion> {
setColorAtPos [.scale.lb.box nearest %y]
}
### The buttons
pack [frame .scale.buttons] -fill x
button .scale.buttons.ok -text OK -command colorOk
button .scale.buttons.cancel -text CANCEL -command colorCancel
pack .scale.buttons.ok .scale.buttons.cancel -padx 5 -side left
### wait until the ok or cancel button has been presed.
tkwait window .scale
if {$__result == ""} {
return [list $defaultColor $greyScaled]
} else {
return [list $__result $__greyscaled]
}
}
######################################################################
# This function is called when the ok button is pressed
######################################################################
proc colorOk {} {
global __result __colorMap
if {[.scale.lb.box curselection] != ""} {
set __result [lindex [lindex $__colorMap [.scale.lb.box curselection]] 0]
} else {
set r [itoh [.scale.0.scale get]]
set g [itoh [.scale.1.scale get]]
set b [itoh [.scale.2.scale get]]
set __result "\#$r$g$b"
}
grab release .scale
destroy .scale
}
######################################################################
# This function is called when the cancel button is pressed
######################################################################
proc colorCancel {} {
global __result
grab release .scale
set __result ""
destroy .scale
}
######################################################################
# This function set the color to the color of the element in the
# listbox at index 'index'. It furher more updates the scales.
# This function is called when an element is selected in the listbox
######################################################################
proc setColorAtPos {index} {
global __colorMap __colorSet
set elm [lindex $__colorMap $index]
set rgb [lindex $elm 1]
set r [lindex $rgb 0]
set g [lindex $rgb 1]
set b [lindex $rgb 2]
set __colorSet 1
.scale.0.scale set $r
.scale.1.scale set $g
.scale.2.scale set $b
.scale.frame.test configure -bg "#[itoh $r][itoh $g][itoh $b]"
update idletasks
set __colorSet 0
}
######################################################################
# This function set the color to the color of the scales
# iff the greyscaled options isn't set. Iff it's set, the scales
# and the palete is set to the color of rgb='index,index,index'
######################################################################
proc setColor {index} {
global __greyscaled __colorSet
if {$__colorSet} {
return
}
if {$__greyscaled} {
.scale.frame.test configure \
-bg "#[itoh $index][itoh $index][itoh $index]"
for {set i 0} {$i < 3} {incr i} {
.scale.$i.scale set $index
}
} else {
set r [itoh [.scale.0.scale get]]
set g [itoh [.scale.1.scale get]]
set b [itoh [.scale.2.scale get]]
.scale.frame.test configure -bg "#$r$g$b"
}
.scale.lb.box selection clear 0 end
}
######################################################################
# This function converts the output from the showrgb program to
# a list which can be use by the color widget
######################################################################
proc showRgb2list {} {
global setup
set path [auto_execok showrgb]
if {$path != 0 && $path != ""} {
set names {}
set lines [split [exec showrgb] "\n"]
foreach line $lines {
set r [lindex $line 0]
set g [lindex $line 1]
set b [lindex $line 2]
set name [string tolower [lrange $line 3 end]]
set color($name) [list $r $g $b]
}
set colors [lsort [array names color]]
foreach name $colors {
lappend names [list $name $color($name)]
}
return $names
} else {
return ""
}
}
######################################################################
# This function compares two string case insensitive.
# OBSOLETE!
######################################################################
proc caseInsensitiveMatch {string1 string2} {
set length1 [string length $string1]
set length2 [string length $string2]
if {$length1 < $length2} {
set min $length1
} else {
set min $length2
}
for {set i 0} {$i < $min} {incr i} {
set c1 [string index $string1 $i]
set c2 [string index $string2 $i]
if {[charLess $c1 $c2]} {
return -1
}
if {[charLess $c2 $c1]} {
return 1
}
}
if {$length1 < $length2} {
return -1
}
if {$length1 > $length2} {
return 1
}
return 0
}
######################################################################
# This function compares two letters case insensitice
######################################################################
proc charLess {c1 c2} {
set chars "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"
set i1 [string first $c1 $chars ]
set i2 [string first $c2 $chars]
return [expr $i1 < $i2]
}
######################################################################
# This function return the color name which is closest to a given
# rgb value
######################################################################
proc findClosestColor {rgb {colorList "NONE"}} {
if {![regexp {\#([0-9ABCDEF][0-9ABCDEF])([0-9ABCDEF][0-9ABCDEF])([0-9ABCDEF][0-9ABCDEF])$} $rgb all rh gh bh]} {
error "Internal error: $rgb didn't match pattern"
}
set r [htoi $rh]
set g [htoi $gh]
set b [htoi $bh]
global __colorMap __closestColor
set minDist 200000
set minName ""
set index 0
set minIndex 0
if {$colorList == "NONE"} {
set colorMap $__colorMap
} else {
set colorMap $colorList
}
foreach color $colorMap {
set name [lindex $color 0]
set _r [lindex [lindex $color 1] 0]
set _g [lindex [lindex $color 1] 1]
set _b [lindex [lindex $color 1] 2]
set dr [expr $r - $_r]
set dg [expr $g - $_g]
set db [expr $b - $_b]
set dist [expr $dr * $dr + $dg * $dg + $db * $db]
if {$dist < $minDist} {
set minDist $dist
set minName $name
set r_ $_r
set g_ $_g
set b_ $_b
set minIndex $index
}
incr index
}
set __closestColor [list $minIndex $r_ $g_ $b_]
return $minName
}
######################################################################
# This function search for the closes color to the one selected with
# the scales. When it has found one, the element in the listbox
# is selected
######################################################################
proc testClosestColor {} {
global __closestColor __origColor __colorSet
set current_r [.scale.0.scale get]
set current_g [.scale.1.scale get]
set current_b [.scale.2.scale get]
set __colorSet 1
if {[info exists __closestColor]} {
set closest_index [lindex $__closestColor 0]
set closest_r [lindex $__closestColor 1]
set closest_g [lindex $__closestColor 2]
set closest_b [lindex $__closestColor 3]
set orig_r [lindex $__origColor 0]
set orig_g [lindex $__origColor 1]
set orig_b [lindex $__origColor 2]
if {$current_r == $orig_r &&
$current_g == $orig_g &&
$current_b == $orig_b} {
.scale.0.scale set $closest_r
.scale.1.scale set $closest_g
.scale.2.scale set $closest_b
.scale.frame.test configure \
-bg "#[itoh $closest_r][itoh $closest_g][itoh $closest_b]"
.scale.lb.box selection set $closest_index
.scale.lb.box yview $closest_index
} elseif {$current_r == $closest_r &&
$current_g == $closest_g &&
$current_b == $closest_b} {
.scale.0.scale set $orig_r
.scale.1.scale set $orig_g
.scale.2.scale set $orig_b
.scale.frame.test configure \
-bg "#[itoh $orig_r][itoh $orig_g][itoh $orig_b]"
.scale.lb.box selection clear 0 end
} else {
findClosestColor "\#[itoh $current_r][itoh $current_g][itoh $current_b]"
set __origColor [list $current_r $current_g $current_b]
.scale.0.scale set [lindex $__closestColor 1]
.scale.1.scale set [lindex $__closestColor 2]
.scale.2.scale set [lindex $__closestColor 3]
.scale.frame.test configure \
-bg "#[itoh $current_r][itoh $current_g][itoh $current_b]"
.scale.lb.box selection set [lindex $__closestColor 0]
.scale.lb.box yview [lindex $__closestColor 0]
}
} else {
findClosestColor "\#[itoh $current_r][itoh $current_g][itoh $current_b]"
set __origColor [list $current_r $current_g $current_b]
.scale.0.scale set [lindex $__closestColor 1]
.scale.1.scale set [lindex $__closestColor 2]
.scale.2.scale set [lindex $__closestColor 3]
.scale.frame.test configure \
-bg \#[itoh [lindex $__closestColor 1]][itoh [lindex $__closestColor 2]][itoh [lindex $__closestColor 3]]
.scale.lb.box selection set [lindex $__closestColor 0]
.scale.lb.box yview [lindex $__closestColor 0]
}
update
set __colorSet 0
}
|