3 # This file contains procedures that change the color palette used
6 # RCS: @(#) $Id: palette.tcl,v 1.12 2007/05/09 12:51:55 das Exp $
8 # Copyright (c) 1995-1997 Sun Microsystems, Inc.
10 # See the file "license.terms" for information on usage and redistribution
11 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 # Changes the default color scheme for a Tk application by setting
16 # default colors in the option database and by modifying all of the
17 # color options for existing widgets that have the default value.
20 # The arguments consist of either a single color name, which
21 # will be used as the new background color (all other colors will
22 # be computed from this) or an even number of values consisting of
23 # option names and values. The name for an option is the one used
24 # for the option database, such as activeForeground, not -activeforeground.
26 proc ::tk_setPalette {args
} {
27 if {[winfo depth .
] == 1} {
28 # Just return on monochrome displays, otherwise errors will occur
32 # Create an array that has the complete new palette. If some colors
33 # aren't specified, compute them from other colors that are specified.
35 if {[llength $args] == 1} {
36 set new
(background
) [lindex $args 0]
40 if {![info exists new
(background
)]} {
41 error "must specify a background color"
43 set bg
[winfo rgb .
$new(background
)]
44 if {![info exists new
(foreground
)]} {
45 # Note that the range of each value in the triple returned by
46 # [winfo rgb] is 0-65535, and your eyes are more sensitive to
47 # green than to red, and more to red than to blue.
48 foreach {r g b
} $bg {break}
49 if {$r+1.5*$g+0.5*$b > 100000} {
50 set new
(foreground
) black
52 set new
(foreground
) white
55 lassign
[winfo rgb .
$new(foreground
)] fg_r fg_g fg_b
56 lassign
$bg bg_r bg_g bg_b
57 set darkerBg
[format #%02x%02x%02x [expr {(9*$bg_r)/2560}] \
58 [expr {(9*$bg_g)/2560}] [expr {(9*$bg_b)/2560}]]
60 foreach i
{activeForeground insertBackground selectForeground
\
62 if {![info exists new
($i)]} {
63 set new
($i) $new(foreground
)
66 if {![info exists new
(disabledForeground
)]} {
67 set new
(disabledForeground
) [format #%02x%02x%02x \
68 [expr {(3*$bg_r + $fg_r)/1024}] \
69 [expr {(3*$bg_g + $fg_g)/1024}] \
70 [expr {(3*$bg_b + $fg_b)/1024}]]
72 if {![info exists new
(highlightBackground
)]} {
73 set new
(highlightBackground
) $new(background
)
75 if {![info exists new
(activeBackground
)]} {
76 # Pick a default active background that islighter than the
77 # normal background. To do this, round each color component
78 # up by 15% or 1/3 of the way to full white, whichever is
81 foreach i
{0 1 2} color
$bg {
82 set light
($i) [expr {$color/256}]
83 set inc1
[expr {($light($i)*15)/100}]
84 set inc2
[expr {(255-$light($i))/3}]
90 if {$light($i) > 255} {
94 set new
(activeBackground
) [format #%02x%02x%02x $light(0) \
97 if {![info exists new
(selectBackground
)]} {
98 set new
(selectBackground
) $darkerBg
100 if {![info exists new
(troughColor
)]} {
101 set new
(troughColor
) $darkerBg
103 if {![info exists new
(selectColor
)]} {
104 set new
(selectColor
) #b03060
107 # let's make one of each of the widgets so we know what the
108 # defaults are currently for this platform.
109 toplevel .___tk_set_palette
110 wm withdraw .___tk_set_palette
112 button canvas checkbutton entry frame label labelframe
113 listbox menubutton menu message radiobutton scale scrollbar
116 $q .___tk_set_palette.
$q
119 # Walk the widget hierarchy, recoloring all existing windows.
120 # The option database must be set according to what we do here,
121 # but it breaks things if we set things in the database while
122 # we are changing colors...so, ::tk::RecolorTree now returns the
123 # option database changes that need to be made, and they
124 # need to be evalled here to take effect.
125 # We have to walk the whole widget tree instead of just
126 # relying on the widgets we've created above to do the work
127 # because different extensions may provide other kinds
128 # of widgets that we don't currently know about, so we'll
129 # walk the whole hierarchy just in case.
131 eval [tk::RecolorTree . new
]
133 destroy .___tk_set_palette
135 # Change the option database so that future windows will get the
138 foreach option [array names new
] {
139 option add
*$option $new($option) widgetDefault
142 # Save the options in the variable ::tk::Palette, for use the
143 # next time we change the options.
145 array set ::tk::Palette [array get new
]
148 # ::tk::RecolorTree --
149 # This procedure changes the colors in a window and all of its
150 # descendants, according to information provided by the colors
151 # argument. This looks at the defaults provided by the option
152 # database, if it exists, and if not, then it looks at the default
153 # value of the widget itself.
156 # w - The name of a window. This window and all its
157 # descendants are recolored.
158 # colors - The name of an array variable in the caller,
159 # which contains color information. Each element
160 # is named after a widget configuration option, and
161 # each value is the value for that option.
163 proc ::tk::RecolorTree {w
colors} {
166 set prototype .___tk_set_palette.
[string tolower
[winfo class
$w]]
167 if {![winfo exists
$prototype]} {
170 foreach dbOption
[array names c
] {
171 set option -[string tolower
$dbOption]
172 set class
[string replace
$dbOption 0 0 [string toupper
\
173 [string index
$dbOption 0]]]
174 if {![catch {$w configure
$option} value
]} {
175 # if the option database has a preference for this
176 # dbOption, then use it, otherwise use the defaults
178 set defaultcolor
[option get
$w $dbOption $class]
179 if {$defaultcolor eq
"" ||
\
180 ([info exists prototype
] && \
181 [$prototype cget
$option] ne
"$defaultcolor")} {
182 set defaultcolor
[lindex $value 3]
184 if {$defaultcolor ne
""} {
185 set defaultcolor
[winfo rgb .
$defaultcolor]
187 set chosencolor
[lindex $value 4]
188 if {$chosencolor ne
""} {
189 set chosencolor
[winfo rgb .
$chosencolor]
191 if {[string match
$defaultcolor $chosencolor]} {
192 # Change the option database so that future windows will get
194 append result
";\noption add [list \
195 *[winfo class $w].$dbOption $c($dbOption) 60]"
196 $w configure
$option $c($dbOption)
200 foreach child
[winfo children
$w] {
201 append result
";\n[::tk::RecolorTree $child c]"
207 # Given a color name, computes a new color value that darkens (or
208 # brightens) the given color by a given percent.
211 # color - Name of starting color.
212 # perecent - Integer telling how much to brighten or darken as a
213 # percent: 50 means darken by 50%, 110 means brighten
216 proc ::tk::Darken {color percent
} {
217 foreach {red green blue
} [winfo rgb .
$color] {
218 set red
[expr {($red/256)*$percent/100}]
219 set green
[expr {($green/256)*$percent/100}]
220 set blue
[expr {($blue/256)*$percent/100}]
232 return [format "#%02x%02x%02x" $red $green $blue]
236 # Reset the Tk color palette to the old "bisque" colors.
241 proc ::tk_bisque {} {
242 tk_setPalette activeBackground
#e6ceb1 activeForeground black \
243 background
#ffe4c4 disabledForeground #b0b0b0 foreground black \
244 highlightBackground
#ffe4c4 highlightColor black \
245 insertBackground black selectColor
#b03060 \
246 selectBackground
#e6ceb1 selectForeground black \