3 # This file contains procedures that change the color palette used
6 # RCS: @(#) $Id: palette.tcl,v 1.5 1999/09/02 17:02:53 hobbs 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
34 # Create an array that has the complete new palette. If some colors
35 # aren't specified, compute them from other colors that are specified.
37 if {[llength $args] == 1} {
38 set new(background) [lindex $args 0]
42 if {![info exists new(background)]} {
43 error "must specify a background color"
45 if {![info exists new(foreground)]} {
46 set new(foreground) black
48 set bg [winfo rgb . $new(background)]
49 set fg [winfo rgb . $new(foreground)]
50 set darkerBg [format #%02x%02x%02x [expr {(9*[lindex $bg 0])/2560}] \
51 [expr {(9*[lindex $bg 1])/2560}] [expr {(9*[lindex $bg 2])/2560}]]
52 foreach i {activeForeground insertBackground selectForeground \
54 if {![info exists new($i)]} {
55 set new($i) $new(foreground)
58 if {![info exists new(disabledForeground)]} {
59 set new(disabledForeground) [format #%02x%02x%02x \
60 [expr {(3*[lindex $bg 0] + [lindex $fg 0])/1024}] \
61 [expr {(3*[lindex $bg 1] + [lindex $fg 1])/1024}] \
62 [expr {(3*[lindex $bg 2] + [lindex $fg 2])/1024}]]
64 if {![info exists new(highlightBackground)]} {
65 set new(highlightBackground) $new(background)
67 if {![info exists new(activeBackground)]} {
68 # Pick a default active background that islighter than the
69 # normal background. To do this, round each color component
70 # up by 15% or 1/3 of the way to full white, whichever is
74 set light($i) [expr {[lindex $bg $i]/256}]
75 set inc1 [expr {($light($i)*15)/100}]
76 set inc2 [expr {(255-$light($i))/3}]
82 if {$light($i) > 255} {
86 set new(activeBackground) [format #%02x%02x%02x $light(0) \
89 if {![info exists new(selectBackground)]} {
90 set new(selectBackground) $darkerBg
92 if {![info exists new(troughColor)]} {
93 set new(troughColor) $darkerBg
95 if {![info exists new(selectColor)]} {
96 set new(selectColor) #b03060
99 # let's make one of each of the widgets so we know what the
100 # defaults are currently for this platform.
101 toplevel .___tk_set_palette
102 wm withdraw .___tk_set_palette
103 foreach q {button canvas checkbutton entry frame label listbox \
104 menubutton menu message radiobutton scale scrollbar text} {
105 $q .___tk_set_palette.$q
108 # Walk the widget hierarchy, recoloring all existing windows.
109 # The option database must be set according to what we do here,
110 # but it breaks things if we set things in the database while
111 # we are changing colors...so, tkRecolorTree now returns the
112 # option database changes that need to be made, and they
113 # need to be evalled here to take effect.
114 # We have to walk the whole widget tree instead of just
115 # relying on the widgets we've created above to do the work
116 # because different extensions may provide other kinds
117 # of widgets that we don't currently know about, so we'll
118 # walk the whole hierarchy just in case.
120 eval [tkRecolorTree . new]
122 catch {destroy .___tk_set_palette}
124 # Change the option database so that future windows will get the
127 foreach option [array names new] {
128 option add *$option $new($option) widgetDefault
131 # Save the options in the global variable tkPalette, for use the
132 # next time we change the options.
134 array set tkPalette [array get new]
138 # This procedure changes the colors in a window and all of its
139 # descendants, according to information provided by the colors
140 # argument. This looks at the defaults provided by the option
141 # database, if it exists, and if not, then it looks at the default
142 # value of the widget itself.
145 # w - The name of a window. This window and all its
146 # descendants are recolored.
147 # colors - The name of an array variable in the caller,
148 # which contains color information. Each element
149 # is named after a widget configuration option, and
150 # each value is the value for that option.
152 proc tkRecolorTree {w colors} {
156 foreach dbOption [array names c] {
157 set option -[string tolower $dbOption]
158 if {![catch {$w config $option} value]} {
159 # if the option database has a preference for this
160 # dbOption, then use it, otherwise use the defaults
162 set defaultcolor [option get $w $dbOption widgetDefault]
163 if {[string match {} $defaultcolor]} {
164 set defaultcolor [winfo rgb . [lindex $value 3]]
166 set defaultcolor [winfo rgb . $defaultcolor]
168 set chosencolor [winfo rgb . [lindex $value 4]]
169 if {[string match $defaultcolor $chosencolor]} {
170 # Change the option database so that future windows will get
172 append result ";\noption add [list \
173 *[winfo class $w].$dbOption $c($dbOption) 60]"
174 $w configure $option $c($dbOption)
178 foreach child [winfo children $w] {
179 append result ";\n[tkRecolorTree $child c]"
185 # Given a color name, computes a new color value that darkens (or
186 # brightens) the given color by a given percent.
189 # color - Name of starting color.
190 # perecent - Integer telling how much to brighten or darken as a
191 # percent: 50 means darken by 50%, 110 means brighten
194 proc tkDarken {color percent} {
195 foreach {red green blue} [winfo rgb . $color] {
196 set red [expr {($red/256)*$percent/100}]
197 set green [expr {($green/256)*$percent/100}]
198 set blue [expr {($blue/256)*$percent/100}]
210 return [format "#%02x%02x%02x" $red $green $blue]
214 # Reset the Tk color palette to the old "bisque" colors.
220 tk_setPalette activeBackground #e6ceb1 activeForeground black \
221 background #ffe4c4 disabledForeground #b0b0b0 foreground black \
222 highlightBackground #ffe4c4 highlightColor black \
223 insertBackground black selectColor #b03060 \
224 selectBackground #e6ceb1 selectForeground black \