# Functions for converting colors and modifying the color scheme of
_MAX_RGB
= float(256 * 256 - 1) # max size of rgb values returned from Tk
def setscheme(root
, background
=None, **kw
):
palette
= apply(_calcPalette
, (root
, background
,), kw
)
for option
, value
in palette
.items():
root
.option_add('*' + option
, value
, 'widgetDefault')
def getdefaultpalette(root
):
# Return the default values of all options, using the defaults
ckbtn
= Tkinter
.Checkbutton(root
)
entry
= Tkinter
.Entry(root
)
scbar
= Tkinter
.Scrollbar(root
)
orig
['activeBackground'] = str(ckbtn
.configure('activebackground')[4])
orig
['activeForeground'] = str(ckbtn
.configure('activeforeground')[4])
orig
['background'] = str(ckbtn
.configure('background')[4])
orig
['disabledForeground'] = str(ckbtn
.configure('disabledforeground')[4])
orig
['foreground'] = str(ckbtn
.configure('foreground')[4])
orig
['highlightBackground'] = str(ckbtn
.configure('highlightbackground')[4])
orig
['highlightColor'] = str(ckbtn
.configure('highlightcolor')[4])
orig
['insertBackground'] = str(entry
.configure('insertbackground')[4])
orig
['selectColor'] = str(ckbtn
.configure('selectcolor')[4])
orig
['selectBackground'] = str(entry
.configure('selectbackground')[4])
orig
['selectForeground'] = str(entry
.configure('selectforeground')[4])
orig
['troughColor'] = str(scbar
.configure('troughcolor')[4])
#======================================================================
# Functions dealing with brightness, hue, saturation and intensity of colors.
def changebrightness(root
, colorName
, brightness
):
# Convert the color name into its hue and back into a color of the
rgb
= name2rgb(root
, colorName
)
hue
, saturation
, intensity
= rgb2hsi(rgb
)
return hue2name(hue
, brightness
)
def hue2name(hue
, brightness
= None):
# Convert the requested hue and brightness into a color name. If
# hue is None, return a grey of the requested brightness.
rgb
= hsi2rgb(0.0, 0.0, brightness
)
rgb
= hsi2rgb(hue
, 1.0, 1.0)
if brightness
is not None:
i
= 1.0 - (1.0 - brightness
) * b
s
= bhi2saturation(brightness
, hue
, i
)
def bhi2saturation(brightness
, hue
, intensity
):
f
= hue
- math
.floor(hue
)
pt
= intensity
- intensity
* f
if hue
== 0: rgb
= (pv
, pt
, pp
)
elif hue
== 1: rgb
= (pq
, pv
, pp
)
elif hue
== 2: rgb
= (pp
, pv
, pt
)
elif hue
== 3: rgb
= (pp
, pq
, pv
)
elif hue
== 4: rgb
= (pt
, pp
, pv
)
elif hue
== 5: rgb
= (pv
, pp
, pq
)
return (intensity
- brightness
) / rgb2brightness(rgb
)
def hsi2rgb(hue
, saturation
, intensity
):
f
= hue
- math
.floor(hue
)
p
= i
* (1.0 - saturation
)
q
= i
* (1.0 - saturation
* f
)
t
= i
* (1.0 - saturation
* (1.0 - f
))
if hue
== 0: rgb
= [i
, t
, p
]
elif hue
== 1: rgb
= [q
, i
, p
]
elif hue
== 2: rgb
= [p
, i
, t
]
elif hue
== 3: rgb
= [p
, q
, i
]
elif hue
== 4: rgb
= [t
, p
, i
]
elif hue
== 5: rgb
= [i
, p
, q
]
def average(rgb1
, rgb2
, fraction
):
rgb2
[0] * fraction
+ rgb1
[0] * (1.0 - fraction
),
rgb2
[1] * fraction
+ rgb1
[1] * (1.0 - fraction
),
rgb2
[2] * fraction
+ rgb1
[2] * (1.0 - fraction
)
return '#%02x%02x%02x' % \
(int(rgb
[0] * 255), int(rgb
[1] * 255), int(rgb
[2] * 255))
# Return the perceived grey level of the color
# (0.0 == black, 1.0 == white).
return rf
* rgb
[0] + gf
* rgb
[1] + bf
* rgb
[2]
maxc
= max(rgb
[0], rgb
[1], rgb
[2])
minc
= min(rgb
[0], rgb
[1], rgb
[2])
saturation
= (maxc
- minc
) / maxc
c
.append((maxc
- rgb
[index
]) / (maxc
- minc
))
return (hue
, saturation
, intensity
)
def name2rgb(root
, colorName
, asInt
= 0):
# Extract rgb information from the color name itself, assuming
# it is either #rgb, #rrggbb, #rrrgggbbb, or #rrrrggggbbbb
# This is useful, since tk may return incorrect rgb values if
# the colormap is full - it will return the rbg values of the
# closest color available.
colorName
= colorName
[1:]
digits
= len(colorName
) / 3
factor
= 16 ** (4 - digits
)
string
.atoi(colorName
[0:digits
], 16) * factor
,
string
.atoi(colorName
[digits
:digits
* 2], 16) * factor
,
string
.atoi(colorName
[digits
* 2:digits
* 3], 16) * factor
,
# We have no choice but to ask Tk what the rgb values are.
rgb
= root
.winfo_rgb(colorName
)
rgb
= (rgb
[0] / _MAX_RGB
, rgb
[1] / _MAX_RGB
, rgb
[2] / _MAX_RGB
)
def _calcPalette(root
, background
=None, **kw
):
# Create a map that has the complete new palette. If some colors
# aren't specified, compute them from other colors that are specified.
for key
, value
in kw
.items():
if background
is not None:
new
['background'] = background
if not new
.has_key('background'):
raise ValueError, 'must specify a background color'
if not new
.has_key('foreground'):
new
['foreground'] = 'black'
bg
= name2rgb(root
, new
['background'])
fg
= name2rgb(root
, new
['foreground'])
for i
in ('activeForeground', 'insertBackground', 'selectForeground',
new
[i
] = new
['foreground']
if not new
.has_key('disabledForeground'):
newCol
= average(bg
, fg
, 0.3)
new
['disabledForeground'] = rgb2name(newCol
)
if not new
.has_key('highlightBackground'):
new
['highlightBackground'] = new
['background']
# Set <lighterBg> to a color that is a little lighter that the
# normal background. To do this, round each color component up by
# 9% or 1/3 of the way to full white, whichever is greater.
inc1
= lighterBg
[i
] * 0.09
inc2
= (1.0 - lighterBg
[i
]) / 3
lighterBg
[i
] = lighterBg
[i
] + inc1
lighterBg
[i
] = lighterBg
[i
] + inc2
# Set <darkerBg> to a color that is a little darker that the
darkerBg
= (bg
[0] * 0.9, bg
[1] * 0.9, bg
[2] * 0.9)
if not new
.has_key('activeBackground'):
# If the foreground is dark, pick a light active background.
# If the foreground is light, pick a dark active background.
# XXX This has been disabled, since it does not look very
# good with dark backgrounds. If this is ever fixed, the
# selectBackground and troughColor options should also be fixed.
if rgb2brightness(fg
) < 0.5:
new
['activeBackground'] = rgb2name(lighterBg
)
new
['activeBackground'] = rgb2name(lighterBg
)
if not new
.has_key('selectBackground'):
new
['selectBackground'] = rgb2name(darkerBg
)
if not new
.has_key('troughColor'):
new
['troughColor'] = rgb2name(darkerBg
)
if not new
.has_key('selectColor'):
new
['selectColor'] = 'yellow'
def spectrum(numColors
, correction
= 1.0, saturation
= 1.0, intensity
= 1.0,
extraOrange
= 1, returnHues
= 0):
division
= numColors
/ 7.0
for index
in range(numColors
):
hue
= 2 + 2 * (index
- 2 * division
) / division
hue
= index
* _TWO_PI
/ numColors
rgb
= hsi2rgb(hue
, saturation
, intensity
)
rgb
= correct(rgb
, correction
)
def correct(rgb
, correction
):
correction
= float(correction
)
rtn
.append((1 - (1 - rgb
[index
]) ** correction
) ** (1 / correction
))
#==============================================================================
def _recolorTree(widget
, oldpalette
, newcolors
):
# Change the colors in a widget and its descendants.
# Change the colors in <widget> and all of its descendants,
# according to the <newcolors> dictionary. It only modifies
# colors that have their default values as specified by the
# <oldpalette> variable. The keys of the <newcolors> dictionary
# are named after widget configuration options and the values are
# the new value for that option.
for dbOption
in newcolors
.keys():
option
= string
.lower(dbOption
)
value
= str(widget
.cget(option
))
if oldpalette
is None or value
== oldpalette
[dbOption
]:
apply(widget
.configure
, (), {option
: newcolors
[dbOption
]})
for child
in widget
.winfo_children():
_recolorTree(child
, oldpalette
, newcolors
)
def changecolor(widget
, background
=None, **kw
):
if not hasattr(widget
, '_Pmw_oldpalette'):
widget
._Pmw
_oldpalette
= getdefaultpalette(root
)
newpalette
= apply(_calcPalette
, (root
, background
,), kw
)
_recolorTree(widget
, widget
._Pmw
_oldpalette
, newpalette
)
widget
._Pmw
_oldpalette
= newpalette
def bordercolors(root
, colorName
):
# This is the same method that Tk uses for shadows, in TkpGetShadows.
for value
in name2rgb(root
, colorName
, 1):
value40pc
= (14 * value
) / 10
valueHalfWhite
= (_MAX_RGB
+ value
) / 2;
lightRGB
.append(max(value40pc
, valueHalfWhite
))
darkValue
= (60 * value
) / 100
darkRGB
.append(darkValue
)
'#%04x%04x%04x' % (lightRGB
[0], lightRGB
[1], lightRGB
[2]),
'#%04x%04x%04x' % (darkRGB
[0], darkRGB
[1], darkRGB
[2])