245 lines
8.0 KiB
Tcl
245 lines
8.0 KiB
Tcl
# palette.tcl --
|
|
#
|
|
# This file contains procedures that change the color palette used
|
|
# by Tk.
|
|
#
|
|
# Copyright (c) 1995-1997 Sun Microsystems, Inc.
|
|
#
|
|
# See the file "license.terms" for information on usage and redistribution
|
|
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
#
|
|
|
|
# ::tk_setPalette --
|
|
# Changes the default color scheme for a Tk application by setting
|
|
# default colors in the option database and by modifying all of the
|
|
# color options for existing widgets that have the default value.
|
|
#
|
|
# Arguments:
|
|
# The arguments consist of either a single color name, which
|
|
# will be used as the new background color (all other colors will
|
|
# be computed from this) or an even number of values consisting of
|
|
# option names and values. The name for an option is the one used
|
|
# for the option database, such as activeForeground, not -activeforeground.
|
|
|
|
proc ::tk_setPalette {args} {
|
|
if {[winfo depth .] == 1} {
|
|
# Just return on monochrome displays, otherwise errors will occur
|
|
return
|
|
}
|
|
|
|
# Create an array that has the complete new palette. If some colors
|
|
# aren't specified, compute them from other colors that are specified.
|
|
|
|
if {[llength $args] == 1} {
|
|
set new(background) [lindex $args 0]
|
|
} else {
|
|
array set new $args
|
|
}
|
|
if {![info exists new(background)]} {
|
|
return -code error -errorcode {TK SET_PALETTE BACKGROUND} \
|
|
"must specify a background color"
|
|
}
|
|
set bg [winfo rgb . $new(background)]
|
|
if {![info exists new(foreground)]} {
|
|
# Note that the range of each value in the triple returned by
|
|
# [winfo rgb] is 0-65535, and your eyes are more sensitive to
|
|
# green than to red, and more to red than to blue.
|
|
foreach {r g b} $bg {break}
|
|
if {$r+1.5*$g+0.5*$b > 100000} {
|
|
set new(foreground) black
|
|
} else {
|
|
set new(foreground) white
|
|
}
|
|
}
|
|
lassign [winfo rgb . $new(foreground)] fg_r fg_g fg_b
|
|
lassign $bg bg_r bg_g bg_b
|
|
set darkerBg [format #%02x%02x%02x [expr {(9*$bg_r)/2560}] \
|
|
[expr {(9*$bg_g)/2560}] [expr {(9*$bg_b)/2560}]]
|
|
|
|
foreach i {activeForeground insertBackground selectForeground \
|
|
highlightColor} {
|
|
if {![info exists new($i)]} {
|
|
set new($i) $new(foreground)
|
|
}
|
|
}
|
|
if {![info exists new(disabledForeground)]} {
|
|
set new(disabledForeground) [format #%02x%02x%02x \
|
|
[expr {(3*$bg_r + $fg_r)/1024}] \
|
|
[expr {(3*$bg_g + $fg_g)/1024}] \
|
|
[expr {(3*$bg_b + $fg_b)/1024}]]
|
|
}
|
|
if {![info exists new(highlightBackground)]} {
|
|
set new(highlightBackground) $new(background)
|
|
}
|
|
if {![info exists new(activeBackground)]} {
|
|
# Pick a default active background that islighter than the
|
|
# normal background. To do this, round each color component
|
|
# up by 15% or 1/3 of the way to full white, whichever is
|
|
# greater.
|
|
|
|
foreach i {0 1 2} color $bg {
|
|
set light($i) [expr {$color/256}]
|
|
set inc1 [expr {($light($i)*15)/100}]
|
|
set inc2 [expr {(255-$light($i))/3}]
|
|
if {$inc1 > $inc2} {
|
|
incr light($i) $inc1
|
|
} else {
|
|
incr light($i) $inc2
|
|
}
|
|
if {$light($i) > 255} {
|
|
set light($i) 255
|
|
}
|
|
}
|
|
set new(activeBackground) [format #%02x%02x%02x $light(0) \
|
|
$light(1) $light(2)]
|
|
}
|
|
if {![info exists new(selectBackground)]} {
|
|
set new(selectBackground) $darkerBg
|
|
}
|
|
if {![info exists new(troughColor)]} {
|
|
set new(troughColor) $darkerBg
|
|
}
|
|
|
|
# let's make one of each of the widgets so we know what the
|
|
# defaults are currently for this platform.
|
|
toplevel .___tk_set_palette
|
|
wm withdraw .___tk_set_palette
|
|
foreach q {
|
|
button canvas checkbutton entry frame label labelframe
|
|
listbox menubutton menu message radiobutton scale scrollbar
|
|
spinbox text
|
|
} {
|
|
$q .___tk_set_palette.$q
|
|
}
|
|
|
|
# Walk the widget hierarchy, recoloring all existing windows.
|
|
# The option database must be set according to what we do here,
|
|
# but it breaks things if we set things in the database while
|
|
# we are changing colors...so, ::tk::RecolorTree now returns the
|
|
# option database changes that need to be made, and they
|
|
# need to be evalled here to take effect.
|
|
# We have to walk the whole widget tree instead of just
|
|
# relying on the widgets we've created above to do the work
|
|
# because different extensions may provide other kinds
|
|
# of widgets that we don't currently know about, so we'll
|
|
# walk the whole hierarchy just in case.
|
|
|
|
eval [tk::RecolorTree . new]
|
|
|
|
destroy .___tk_set_palette
|
|
|
|
# Change the option database so that future windows will get the
|
|
# same colors.
|
|
|
|
foreach option [array names new] {
|
|
option add *$option $new($option) widgetDefault
|
|
}
|
|
|
|
# Save the options in the variable ::tk::Palette, for use the
|
|
# next time we change the options.
|
|
|
|
array set ::tk::Palette [array get new]
|
|
}
|
|
|
|
# ::tk::RecolorTree --
|
|
# This procedure changes the colors in a window and all of its
|
|
# descendants, according to information provided by the colors
|
|
# argument. This looks at the defaults provided by the option
|
|
# database, if it exists, and if not, then it looks at the default
|
|
# value of the widget itself.
|
|
#
|
|
# Arguments:
|
|
# w - The name of a window. This window and all its
|
|
# descendants are recolored.
|
|
# colors - The name of an array variable in the caller,
|
|
# which contains color information. Each element
|
|
# is named after a widget configuration option, and
|
|
# each value is the value for that option.
|
|
|
|
proc ::tk::RecolorTree {w colors} {
|
|
upvar $colors c
|
|
set result {}
|
|
set prototype .___tk_set_palette.[string tolower [winfo class $w]]
|
|
if {![winfo exists $prototype]} {
|
|
unset prototype
|
|
}
|
|
foreach dbOption [array names c] {
|
|
set option -[string tolower $dbOption]
|
|
set class [string replace $dbOption 0 0 [string toupper \
|
|
[string index $dbOption 0]]]
|
|
if {![catch {$w configure $option} value]} {
|
|
# if the option database has a preference for this
|
|
# dbOption, then use it, otherwise use the defaults
|
|
# for the widget.
|
|
set defaultcolor [option get $w $dbOption $class]
|
|
if {$defaultcolor eq "" || \
|
|
([info exists prototype] && \
|
|
[$prototype cget $option] ne "$defaultcolor")} {
|
|
set defaultcolor [lindex $value 3]
|
|
}
|
|
if {$defaultcolor ne ""} {
|
|
set defaultcolor [winfo rgb . $defaultcolor]
|
|
}
|
|
set chosencolor [lindex $value 4]
|
|
if {$chosencolor ne ""} {
|
|
set chosencolor [winfo rgb . $chosencolor]
|
|
}
|
|
if {[string match $defaultcolor $chosencolor]} {
|
|
# Change the option database so that future windows will get
|
|
# the same colors.
|
|
append result ";\noption add [list \
|
|
*[winfo class $w].$dbOption $c($dbOption) 60]"
|
|
$w configure $option $c($dbOption)
|
|
}
|
|
}
|
|
}
|
|
foreach child [winfo children $w] {
|
|
append result ";\n[::tk::RecolorTree $child c]"
|
|
}
|
|
return $result
|
|
}
|
|
|
|
# ::tk::Darken --
|
|
# Given a color name, computes a new color value that darkens (or
|
|
# brightens) the given color by a given percent.
|
|
#
|
|
# Arguments:
|
|
# color - Name of starting color.
|
|
# percent - Integer telling how much to brighten or darken as a
|
|
# percent: 50 means darken by 50%, 110 means brighten
|
|
# by 10%.
|
|
|
|
proc ::tk::Darken {color percent} {
|
|
if {$percent < 0} {
|
|
return #000000
|
|
} elseif {$percent > 200} {
|
|
return #ffffff
|
|
} elseif {$percent <= 100} {
|
|
lassign [winfo rgb . $color] r g b
|
|
set r [expr {($r/256)*$percent/100}]
|
|
set g [expr {($g/256)*$percent/100}]
|
|
set b [expr {($b/256)*$percent/100}]
|
|
} elseif {$percent > 100} {
|
|
lassign [winfo rgb . $color] r g b
|
|
set r [expr {255 - ((65535-$r)/256)*(200-$percent)/100}]
|
|
set g [expr {255 - ((65535-$g)/256)*(200-$percent)/100}]
|
|
set b [expr {255 - ((65535-$b)/256)*(200-$percent)/100}]
|
|
}
|
|
return [format #%02x%02x%02x $r $g $b]
|
|
}
|
|
|
|
# ::tk_bisque --
|
|
# Reset the Tk color palette to the old "bisque" colors.
|
|
#
|
|
# Arguments:
|
|
# None.
|
|
|
|
proc ::tk_bisque {} {
|
|
tk_setPalette activeBackground #e6ceb1 activeForeground black \
|
|
background #ffe4c4 disabledForeground #b0b0b0 foreground black \
|
|
highlightBackground #ffe4c4 highlightColor black \
|
|
insertBackground black \
|
|
selectBackground #e6ceb1 selectForeground black \
|
|
troughColor #cdb79e
|
|
}
|