Update of /cvsroot/wpdev/xmlscripts/python-lib/Pmw/Pmw_1_2/lib
In directory sc8-pr-cvs1:/tmp/cvs-serv17003/Pmw_1_2/lib
Added Files:
__init__.py Pmw.def PmwAboutDialog.py PmwBalloon.py PmwBase.py
PmwBlt.py PmwButtonBox.py PmwColor.py PmwComboBox.py
PmwComboBoxDialog.py PmwCounter.py PmwCounterDialog.py
PmwDialog.py PmwEntryField.py PmwGroup.py PmwHistoryText.py
PmwLabeledWidget.py PmwLoader.py PmwLogicalFont.py
PmwMainMenuBar.py PmwMenuBar.py PmwMessageBar.py
PmwMessageDialog.py PmwNoteBook.py PmwOptionMenu.py
PmwPanedWidget.py PmwPromptDialog.py PmwRadioSelect.py
PmwScrolledCanvas.py PmwScrolledField.py PmwScrolledFrame.py
PmwScrolledListBox.py PmwScrolledText.py PmwSelectionDialog.py
PmwTextDialog.py PmwTimeCounter.py PmwTimeFuncs.py
Log Message:
pmw class wrapers for Tkinter
--- NEW FILE: __init__.py ---
# File to allow this directory to be treated as a python package.
--- NEW FILE: Pmw.def ---
# [Emacs: -*- python -*-]
# --- This is the Pmw definition file ---
#
# It is invoked by the Pmw dynamic loader in Pmw.__init__.
#
# widgets : tuple with the names of those widget classes that are
# stacked in a module of the same name.
# widgetclasses : dictionary from names of widget classes to module names.
# functions : dictionary from function names to modules names.
# modules : tuple of module names that don't contain widget classes
# of the same name.
#
# Widgets whose name is the same as its module.
_widgets = (
'AboutDialog', 'Balloon', 'ButtonBox', 'ComboBox',
'ComboBoxDialog', 'Counter', 'CounterDialog', 'Dialog',
'EntryField', 'Group', 'HistoryText', 'LabeledWidget',
'MainMenuBar', 'MenuBar', 'MessageBar',
'MessageDialog', 'NoteBook', 'OptionMenu', 'PanedWidget',
'PromptDialog', 'RadioSelect', 'ScrolledCanvas', 'ScrolledField',
'ScrolledFrame', 'ScrolledListBox', 'ScrolledText', 'SelectionDialog',
'TextDialog', 'TimeCounter',
)
# Widgets whose name is not the same as its module.
_extraWidgets = {
}
_functions = {
'logicalfont' : 'LogicalFont',
'logicalfontnames' : 'LogicalFont',
'aboutversion' : 'AboutDialog',
'aboutcopyright' : 'AboutDialog',
'aboutcontact' : 'AboutDialog',
'datestringtojdn' : 'TimeFuncs',
'timestringtoseconds' : 'TimeFuncs',
'setyearpivot' : 'TimeFuncs',
'ymdtojdn' : 'TimeFuncs',
'jdntoymd' : 'TimeFuncs',
'stringtoreal' : 'TimeFuncs',
'aligngrouptags' : 'Group',
'OK' : 'EntryField',
'ERROR' : 'EntryField',
'PARTIAL' : 'EntryField',
'numericvalidator' : 'EntryField',
'integervalidator' : 'EntryField',
'hexadecimalvalidator' : 'EntryField',
'realvalidator' : 'EntryField',
'alphabeticvalidator' : 'EntryField',
'alphanumericvalidator' : 'EntryField',
'timevalidator' : 'EntryField',
'datevalidator' : 'EntryField',
}
_modules = (
'Color', 'Blt',
)
--- NEW FILE: PmwAboutDialog.py ---
import Pmw
class AboutDialog(Pmw.MessageDialog):
# Window to display version and contact information.
# Class members containing resettable 'default' values:
_version = ''
_copyright = ''
_contact = ''
def __init__(self, parent = None, **kw):
# Define the megawidget options.
INITOPT = Pmw.INITOPT
optiondefs = (
('applicationname', '', INITOPT),
('iconpos', 'w', None),
('icon_bitmap', 'info', None),
('buttons', ('Close',), None),
('defaultbutton', 0, None),
)
self.defineoptions(kw, optiondefs)
# Initialise the base class (after defining the options).
Pmw.MessageDialog.__init__(self, parent)
applicationname = self['applicationname']
if not kw.has_key('title'):
self.configure(title = 'About ' + applicationname)
if not kw.has_key('message_text'):
text = applicationname + '\n\n'
if AboutDialog._version != '':
text = text + 'Version ' + AboutDialog._version + '\n'
if AboutDialog._copyright != '':
text = text + AboutDialog._copyright + '\n\n'
if AboutDialog._contact != '':
text = text + AboutDialog._contact
self.configure(message_text=text)
# Check keywords and initialise options.
self.initialiseoptions()
def aboutversion(value):
AboutDialog._version = value
def aboutcopyright(value):
AboutDialog._copyright = value
def aboutcontact(value):
AboutDialog._contact = value
--- NEW FILE: PmwBalloon.py ---
import os
import string
import Tkinter
import Pmw
class Balloon(Pmw.MegaToplevel):
def __init__(self, parent = None, **kw):
# Define the megawidget options.
optiondefs = (
('initwait', 500, None), # milliseconds
('label_background', 'lightyellow', None),
('label_foreground', 'black', None),
('label_justify', 'left', None),
('master', 'parent', None),
('relmouse', 'none', self._relmouse),
('state', 'both', self._state),
('statuscommand', None, None),
('xoffset', 20, None), # pixels
('yoffset', 1, None), # pixels
('hull_highlightthickness', 1, None),
('hull_highlightbackground', 'black', None),
)
self.defineoptions(kw, optiondefs)
# Initialise the base class (after defining the options).
Pmw.MegaToplevel.__init__(self, parent)
self.withdraw()
self.overrideredirect(1)
# Create the components.
interior = self.interior()
self._label = self.createcomponent('label',
(), None,
Tkinter.Label, (interior,))
self._label.pack()
# The default hull configuration options give a black border
# around the balloon, but avoids a black 'flash' when the
# balloon is deiconified, before the text appears.
if not kw.has_key('hull_background'):
self.configure(hull_background = \
str(self._label.cget('background')))
# Initialise instance variables.
self._timer = None
# The widget or item that is currently triggering the balloon.
# It is None if the balloon is not being displayed. It is a
# one-tuple if the balloon is being displayed in response to a
# widget binding (value is the widget). It is a two-tuple if
# the balloon is being displayed in response to a canvas or
# text item binding (value is the widget and the item).
self._currentTrigger = None
# Check keywords and initialise options.
self.initialiseoptions()
def destroy(self):
if self._timer is not None:
self.after_cancel(self._timer)
self._timer = None
Pmw.MegaToplevel.destroy(self)
def bind(self, widget, balloonHelp, statusHelp = None):
# If a previous bind for this widget exists, remove it.
self.unbind(widget)
if balloonHelp is None and statusHelp is None:
return
if statusHelp is None:
statusHelp = balloonHelp
enterId = widget.bind('<Enter>',
lambda event, self = self, w = widget,
sHelp = statusHelp, bHelp = balloonHelp:
self._enter(event, w, sHelp, bHelp, 0))
# Set Motion binding so that if the pointer remains at rest
# within the widget until the status line removes the help and
# then the pointer moves again, then redisplay the help in the
# status line.
# Note: The Motion binding only works for basic widgets, and
# the hull of megawidgets but not for other megawidget components.
motionId = widget.bind('<Motion>',
lambda event = None, self = self, statusHelp = statusHelp:
self.showstatus(statusHelp))
leaveId = widget.bind('<Leave>', self._leave)
buttonId = widget.bind('<ButtonPress>', self._buttonpress)
# Set Destroy binding so that the balloon can be withdrawn and
# the timer can be cancelled if the widget is destroyed.
destroyId = widget.bind('<Destroy>', self._destroy)
# Use the None item in the widget's private Pmw dictionary to
# store the widget's bind callbacks, for later clean up.
if not hasattr(widget, '_Pmw_BalloonBindIds'):
widget._Pmw_BalloonBindIds = {}
widget._Pmw_BalloonBindIds[None] = \
(enterId, motionId, leaveId, buttonId, destroyId)
def unbind(self, widget):
if hasattr(widget, '_Pmw_BalloonBindIds'):
if widget._Pmw_BalloonBindIds.has_key(None):
(enterId, motionId, leaveId, buttonId, destroyId) = \
widget._Pmw_BalloonBindIds[None]
# Need to pass in old bindings, so that Tkinter can
# delete the commands. Otherwise, memory is leaked.
widget.unbind('<Enter>', enterId)
widget.unbind('<Motion>', motionId)
widget.unbind('<Leave>', leaveId)
widget.unbind('<ButtonPress>', buttonId)
widget.unbind('<Destroy>', destroyId)
del widget._Pmw_BalloonBindIds[None]
if self._currentTrigger is not None and len(self._currentTrigger) == 1:
# The balloon is currently being displayed and the current
# trigger is a widget.
triggerWidget = self._currentTrigger[0]
if triggerWidget == widget:
if self._timer is not None:
self.after_cancel(self._timer)
self._timer = None
self.withdraw()
self.clearstatus()
self._currentTrigger = None
def tagbind(self, widget, tagOrItem, balloonHelp, statusHelp = None):
# If a previous bind for this widget's tagOrItem exists, remove it.
self.tagunbind(widget, tagOrItem)
if balloonHelp is None and statusHelp is None:
return
if statusHelp is None:
statusHelp = balloonHelp
enterId = widget.tag_bind(tagOrItem, '<Enter>',
lambda event, self = self, w = widget,
sHelp = statusHelp, bHelp = balloonHelp:
self._enter(event, w, sHelp, bHelp, 1))
motionId = widget.tag_bind(tagOrItem, '<Motion>',
lambda event = None, self = self, statusHelp = statusHelp:
self.showstatus(statusHelp))
leaveId = widget.tag_bind(tagOrItem, '<Leave>', self._leave)
buttonId = widget.tag_bind(tagOrItem, '<ButtonPress>', self._buttonpress)
# Use the tagOrItem item in the widget's private Pmw dictionary to
# store the tagOrItem's bind callbacks, for later clean up.
if not hasattr(widget, '_Pmw_BalloonBindIds'):
widget._Pmw_BalloonBindIds = {}
widget._Pmw_BalloonBindIds[tagOrItem] = \
(enterId, motionId, leaveId, buttonId)
def tagunbind(self, widget, tagOrItem):
if hasattr(widget, '_Pmw_BalloonBindIds'):
if widget._Pmw_BalloonBindIds.has_key(tagOrItem):
(enterId, motionId, leaveId, buttonId) = \
widget._Pmw_BalloonBindIds[tagOrItem]
widget.tag_unbind(tagOrItem, '<Enter>', enterId)
widget.tag_unbind(tagOrItem, '<Motion>', motionId)
widget.tag_unbind(tagOrItem, '<Leave>', leaveId)
widget.tag_unbind(tagOrItem, '<ButtonPress>', buttonId)
del widget._Pmw_BalloonBindIds[tagOrItem]
if self._currentTrigger is None:
# The balloon is not currently being displayed.
return
if len(self._currentTrigger) == 1:
# The current trigger is a widget.
return
if len(self._currentTrigger) == 2:
# The current trigger is a canvas item.
(triggerWidget, triggerItem) = self._currentTrigger
if triggerWidget == widget and triggerItem == tagOrItem:
if self._timer is not None:
self.after_cancel(self._timer)
self._timer = None
self.withdraw()
self.clearstatus()
self._currentTrigger = None
else: # The current trigger is a text item.
(triggerWidget, x, y) = self._currentTrigger
if triggerWidget == widget:
currentPos = widget.index('@%d,%d' % (x, y))
currentTags = widget.tag_names(currentPos)
if tagOrItem in currentTags:
if self._timer is not None:
self.after_cancel(self._timer)
self._timer = None
self.withdraw()
self.clearstatus()
self._currentTrigger = None
def showstatus(self, statusHelp):
if self['state'] in ('status', 'both'):
cmd = self['statuscommand']
if callable(cmd):
cmd(statusHelp)
def clearstatus(self):
self.showstatus(None)
def _state(self):
if self['state'] not in ('both', 'balloon', 'status', 'none'):
raise ValueError, 'bad state option ' + repr(self['state']) + \
': should be one of \'both\', \'balloon\', ' + \
'\'status\' or \'none\''
def _relmouse(self):
if self['relmouse'] not in ('both', 'x', 'y', 'none'):
raise ValueError, 'bad relmouse option ' + repr(self['relmouse'])+ \
': should be one of \'both\', \'x\', ' + '\'y\' or \'none\''
def _enter(self, event, widget, statusHelp, balloonHelp, isItem):
# Do not display balloon if mouse button is pressed. This
# will only occur if the button was pressed inside a widget,
# then the mouse moved out of and then back into the widget,
# with the button still held down. The number 0x1f00 is the
# button mask for the 5 possible buttons in X.
buttonPressed = (event.state & 0x1f00) != 0
if not buttonPressed and balloonHelp is not None and \
self['state'] in ('balloon', 'both'):
if self._timer is not None:
self.after_cancel(self._timer)
self._timer = None
self._timer = self.after(self['initwait'],
lambda self = self, widget = widget, help = balloonHelp,
isItem = isItem:
self._showBalloon(widget, help, isItem))
if isItem:
if hasattr(widget, 'canvasx'):
# The widget is a canvas.
item = widget.find_withtag('current')
if len(item) > 0:
item = item[0]
else:
item = None
self._currentTrigger = (widget, item)
else:
# The widget is a text widget.
self._currentTrigger = (widget, event.x, event.y)
else:
self._currentTrigger = (widget,)
self.showstatus(statusHelp)
def _leave(self, event):
if self._timer is not None:
self.after_cancel(self._timer)
self._timer = None
self.withdraw()
self.clearstatus()
self._currentTrigger = None
def _destroy(self, event):
# Only withdraw the balloon and cancel the timer if the widget
# being destroyed is the widget that triggered the balloon.
# Note that in a Tkinter Destroy event, the widget field is a
# string and not a widget as usual.
if self._currentTrigger is None:
# The balloon is not currently being displayed
return
if len(self._currentTrigger) == 1:
# The current trigger is a widget (not an item)
triggerWidget = self._currentTrigger[0]
if str(triggerWidget) == event.widget:
if self._timer is not None:
self.after_cancel(self._timer)
self._timer = None
self.withdraw()
self.clearstatus()
self._currentTrigger = None
def _buttonpress(self, event):
if self._timer is not None:
self.after_cancel(self._timer)
self._timer = None
self.withdraw()
self._currentTrigger = None
def _showBalloon(self, widget, balloonHelp, isItem):
self._label.configure(text = balloonHelp)
# First, display the balloon offscreen to get dimensions.
screenWidth = self.winfo_screenwidth()
screenHeight = self.winfo_screenheight()
self.geometry('+%d+0' % (screenWidth + 1))
self.update_idletasks()
if isItem:
# Get the bounding box of the current item.
bbox = widget.bbox('current')
if bbox is None:
# The item that triggered the balloon has disappeared,
# perhaps by a user's timer event that occured between
# the <Enter> event and the 'initwait' timer calling
# this method.
return
# The widget is either a text or canvas. The meaning of
# the values returned by the bbox method is different for
# each, so use the existence of the 'canvasx' method to
# distinguish between them.
if hasattr(widget, 'canvasx'):
# The widget is a canvas. Place balloon under canvas
# item. The positions returned by bbox are relative
# to the entire canvas, not just the visible part, so
# need to convert to window coordinates.
leftrel = bbox[0] - widget.canvasx(0)
toprel = bbox[1] - widget.canvasy(0)
bottomrel = bbox[3] - widget.canvasy(0)
else:
# The widget is a text widget. Place balloon under
# the character closest to the mouse. The positions
# returned by bbox are relative to the text widget
# window (ie the visible part of the text only).
leftrel = bbox[0]
toprel = bbox[1]
bottomrel = bbox[1] + bbox[3]
else:
leftrel = 0
toprel = 0
bottomrel = widget.winfo_height()
xpointer, ypointer = widget.winfo_pointerxy() # -1 if off screen
if xpointer >= 0 and self['relmouse'] in ('both', 'x'):
x = xpointer
else:
x = leftrel + widget.winfo_rootx()
x = x + self['xoffset']
if ypointer >= 0 and self['relmouse'] in ('both', 'y'):
y = ypointer
else:
y = bottomrel + widget.winfo_rooty()
y = y + self['yoffset']
edges = (string.atoi(str(self.cget('hull_highlightthickness'))) +
string.atoi(str(self.cget('hull_borderwidth')))) * 2
if x + self._label.winfo_reqwidth() + edges > screenWidth:
x = screenWidth - self._label.winfo_reqwidth() - edges
if y + self._label.winfo_reqheight() + edges > screenHeight:
if ypointer >= 0 and self['relmouse'] in ('both', 'y'):
y = ypointer
else:
y = toprel + widget.winfo_rooty()
y = y - self._label.winfo_reqheight() - self['yoffset'] - edges
Pmw.setgeometryanddeiconify(self, '+%d+%d' % (x, y))
--- NEW FILE: PmwBase.py ---
# Pmw megawidget base classes.
# This module provides a foundation for building megawidgets. It
# contains the MegaArchetype class which manages component widgets and
# configuration options. Also provided are the MegaToplevel and
# MegaWidget classes, derived from the MegaArchetype class. The
# MegaToplevel class contains a Tkinter Toplevel widget to act as the
# container of the megawidget. This is used as the base class of all
# megawidgets that are contained in their own top level window, such
# as a Dialog window. The MegaWidget class contains a Tkinter Frame
# to act as the container of the megawidget. This is used as the base
# class of all other megawidgets, such as a ComboBox or ButtonBox.
#
# Megawidgets are built by creating a class that inherits from either
# the MegaToplevel or MegaWidget class.
import os
import string
import sys
[...1894 lines suppressed...]
text = self._errorQueue[0]
del self._errorQueue[0]
self._display(text)
self._updateButtons()
def _display(self, text):
self._errorCount = self._errorCount + 1
text = 'Error: %d\n%s' % (self._errorCount, text)
self._text.delete('1.0', 'end')
self._text.insert('end', text)
def _updateButtons(self):
numQueued = len(self._errorQueue)
if numQueued > 0:
self._label.configure(text='%d more errors' % numQueued)
self._nextError.configure(state='normal')
else:
self._label.configure(text='No more errors')
self._nextError.configure(state='disabled')
--- NEW FILE: PmwBlt.py ---
# Python interface to some of the commands of the 2.4 version of the
# BLT extension to tcl.
import string
import types
import Tkinter
# Supported commands:
_busyCommand = '::blt::busy'
_vectorCommand = '::blt::vector'
_graphCommand = '::blt::graph'
_testCommand = '::blt::*'
_chartCommand = '::blt::stripchart'
_tabsetCommand = '::blt::tabset'
_haveBlt = None
_haveBltBusy = None
def _checkForBlt(window):
global _haveBlt
global _haveBltBusy
# Blt may be a package which has not yet been loaded. Try to load it.
try:
window.tk.call('package', 'require', 'BLT')
except Tkinter.TclError:
# Another way to try to dynamically load blt:
try:
window.tk.call('load', '', 'Blt')
except Tkinter.TclError:
pass
_haveBlt= (window.tk.call('info', 'commands', _testCommand) != '')
_haveBltBusy = (window.tk.call('info', 'commands', _busyCommand) != '')
def haveblt(window):
if _haveBlt is None:
_checkForBlt(window)
return _haveBlt
def havebltbusy(window):
if _haveBlt is None:
_checkForBlt(window)
return _haveBltBusy
def _loadBlt(window):
if _haveBlt is None:
if window is None:
window = Tkinter._default_root
if window is None:
window = Tkinter.Tk()
_checkForBlt(window)
def busy_hold(window, cursor = None):
_loadBlt(window)
if cursor is None:
window.tk.call(_busyCommand, 'hold', window._w)
else:
window.tk.call(_busyCommand, 'hold', window._w, '-cursor', cursor)
def busy_release(window):
_loadBlt(window)
window.tk.call(_busyCommand, 'release', window._w)
def busy_forget(window):
_loadBlt(window)
window.tk.call(_busyCommand, 'forget', window._w)
#=============================================================================
# Interface to the blt vector command which makes it look like the
# builtin python list type.
# The -variable, -command, -watchunset creation options are not supported.
# The dup, merge, notify, offset, populate, seq and variable methods
# and the +, -, * and / operations are not supported.
# Blt vector functions:
def vector_expr(expression):
tk = Tkinter._default_root.tk
strList = tk.splitlist(tk.call(_vectorCommand, 'expr', expression))
return tuple(map(string.atof, strList))
def vector_names(pattern = None):
tk = Tkinter._default_root.tk
return tk.splitlist(tk.call(_vectorCommand, 'names', pattern))
class Vector:
_varnum = 0
def __init__(self, size=None, master=None):
# <size> can be either an integer size, or a string "first:last".
_loadBlt(master)
if master:
self._master = master
else:
self._master = Tkinter._default_root
self.tk = self._master.tk
self._name = 'PY_VEC' + str(Vector._varnum)
Vector._varnum = Vector._varnum + 1
if size is None:
self.tk.call(_vectorCommand, 'create', self._name)
else:
self.tk.call(_vectorCommand, 'create', '%s(%s)' % (self._name, size))
def __del__(self):
self.tk.call(_vectorCommand, 'destroy', self._name)
def __str__(self):
return self._name
def __repr__(self):
return '[' + string.join(map(str, self), ', ') + ']'
def __cmp__(self, list):
return cmp(self[:], list)
def __len__(self):
return self.tk.getint(self.tk.call(self._name, 'length'))
def __getitem__(self, key):
oldkey = key
if key < 0:
key = key + len(self)
try:
return self.tk.getdouble(self.tk.globalgetvar(self._name, str(key)))
except Tkinter.TclError:
raise IndexError, oldkey
def __setitem__(self, key, value):
if key < 0:
key = key + len(self)
return self.tk.globalsetvar(self._name, str(key), float(value))
def __delitem__(self, key):
if key < 0:
key = key + len(self)
return self.tk.globalunsetvar(self._name, str(key))
def __getslice__(self, start, end):
length = len(self)
if start < 0:
start = 0
if end > length:
end = length
if start >= end:
return []
end = end - 1 # Blt vector slices include end point.
text = self.tk.globalgetvar(self._name, str(start) + ':' + str(end))
return map(self.tk.getdouble, self.tk.splitlist(text))
def __setslice__(self, start, end, list):
if start > end:
end = start
self.set(self[:start] + list + self[end:])
def __delslice__(self, start, end):
if start < end:
self.set(self[:start] + self[end:])
def __add__(self, list):
return self[:] + list
def __radd__(self, list):
return list + self[:]
def __mul__(self, n):
return self[:] * n
__rmul__ = __mul__
# Python builtin list methods:
def append(self, *args):
self.tk.call(self._name, 'append', args)
def count(self, obj):
return self[:].count(obj)
def index(self, value):
return self[:].index(value)
def insert(self, index, value):
self[index:index] = [value]
def remove(self, value):
del self[self.index(value)]
def reverse(self):
s = self[:]
s.reverse()
self.set(s)
def sort(self, *args):
s = self[:]
s.sort()
self.set(s)
# Blt vector instance methods:
# append - same as list method above
def clear(self):
self.tk.call(self._name, 'clear')
def delete(self, *args):
self.tk.call((self._name, 'delete') + args)
def expr(self, expression):
self.tk.call(self._name, 'expr', expression)
def length(self, newSize=None):
return self.tk.getint(self.tk.call(self._name, 'length', newSize))
def range(self, first, last=None):
# Note that, unlike self[first:last], this includes the last
# item in the returned range.
text = self.tk.call(self._name, 'range', first, last)
return map(self.tk.getdouble, self.tk.splitlist(text))
def search(self, start, end=None):
return self._master._getints(self.tk.call(
self._name, 'search', start, end))
def set(self, list):
if type(list) != types.TupleType:
list = tuple(list)
self.tk.call(self._name, 'set', list)
# The blt vector sort method has different semantics to the python
# list sort method. Call these blt_sort:
def blt_sort(self, *args):
self.tk.call((self._name, 'sort') + args)
def blt_sort_reverse(self, *args):
self.tk.call((self._name, 'sort', '-reverse') + args)
# Special blt vector indexes:
def min(self):
return self.tk.getdouble(self.tk.globalgetvar(self._name, 'min'))
def max(self):
return self.tk.getdouble(self.tk.globalgetvar(self._name, 'max'))
# Method borrowed from Tkinter.Var class:
def get(self):
return self[:]
#=============================================================================
# This is a general purpose configure routine which can handle the
# configuration of widgets, items within widgets, etc. Supports the
# forms configure() and configure('font') for querying and
# configure(font = 'fixed', text = 'hello') for setting.
def _doConfigure(widget, subcommand, option, kw):
if not option and not kw:
# Return a description of all options.
ret = {}
options = widget.tk.splitlist(widget.tk.call(subcommand))
for optionString in options:
optionInfo = widget.tk.splitlist(optionString)
option = optionInfo[0][1:]
ret[option] = (option,) + optionInfo[1:]
return ret
if option:
# Return a description of the option given by <option>.
if kw:
# Having keywords implies setting configuration options.
# Can't set and get in one command!
raise ValueError, 'cannot have option argument with keywords'
option = '-' + option
optionInfo = widget.tk.splitlist(widget.tk.call(subcommand + (option,)))
return (optionInfo[0][1:],) + optionInfo[1:]
# Otherwise, set the given configuration options.
widget.tk.call(subcommand + widget._options(kw))
#=============================================================================
class Graph(Tkinter.Widget):
# Wrapper for the blt graph widget, version 2.4.
def __init__(self, master=None, cnf={}, **kw):
_loadBlt(master)
Tkinter.Widget.__init__(self, master, _graphCommand, cnf, kw)
def bar_create(self, name, **kw):
self.tk.call((self._w, 'bar', 'create', name) + self._options(kw))
def line_create(self, name, **kw):
self.tk.call((self._w, 'line', 'create', name) + self._options(kw))
def extents(self, item):
return self.tk.getint(self.tk.call(self._w, 'extents', item))
def invtransform(self, winX, winY):
return self._getdoubles(
self.tk.call(self._w, 'invtransform', winX, winY))
def inside(self, x, y):
return self.tk.getint(self.tk.call(self._w, 'inside', x, y))
def snap(self, photoName):
self.tk.call(self._w, 'snap', photoName)
def transform(self, x, y):
return self._getdoubles(self.tk.call(self._w, 'transform', x, y))
def axis_cget(self, axisName, key):
return self.tk.call(self._w, 'axis', 'cget', axisName, '-' + key)
def axis_configure(self, axes, option=None, **kw):
# <axes> may be a list of axisNames.
if type(axes) == types.StringType:
axes = [axes]
subcommand = (self._w, 'axis', 'configure') + tuple(axes)
return _doConfigure(self, subcommand, option, kw)
def axis_create(self, axisName, **kw):
self.tk.call((self._w, 'axis', 'create', axisName) + self._options(kw))
def axis_delete(self, *args):
self.tk.call((self._w, 'axis', 'delete') + args)
def axis_invtransform(self, axisName, value):
return self.tk.getdouble(self.tk.call(
self._w, 'axis', 'invtransform', axisName, value))
def axis_limits(self, axisName):
return self._getdoubles(self.tk.call(
self._w, 'axis', 'limits', axisName))
def axis_names(self, *args):
return self.tk.splitlist(
self.tk.call((self._w, 'axis', 'names') + args))
def axis_transform(self, axisName, value):
return self.tk.getint(self.tk.call(
self._w, 'axis', 'transform', axisName, value))
def xaxis_cget(self, key):
return self.tk.call(self._w, 'xaxis', 'cget', '-' + key)
def xaxis_configure(self, option=None, **kw):
subcommand = (self._w, 'xaxis', 'configure')
return _doConfigure(self, subcommand, option, kw)
def xaxis_invtransform(self, value):
return self.tk.getdouble(self.tk.call(
self._w, 'xaxis', 'invtransform', value))
def xaxis_limits(self):
return self._getdoubles(self.tk.call(self._w, 'xaxis', 'limits'))
def xaxis_transform(self, value):
return self.tk.getint(self.tk.call(
self._w, 'xaxis', 'transform', value))
def xaxis_use(self, axisName = None):
return self.tk.call(self._w, 'xaxis', 'use', axisName)
def x2axis_cget(self, key):
return self.tk.call(self._w, 'x2axis', 'cget', '-' + key)
def x2axis_configure(self, option=None, **kw):
subcommand = (self._w, 'x2axis', 'configure')
return _doConfigure(self, subcommand, option, kw)
def x2axis_invtransform(self, value):
return self.tk.getdouble(self.tk.call(
self._w, 'x2axis', 'invtransform', value))
def x2axis_limits(self):
return self._getdoubles(self.tk.call(self._w, 'x2axis', 'limits'))
def x2axis_transform(self, value):
return self.tk.getint(self.tk.call(
self._w, 'x2axis', 'transform', value))
def x2axis_use(self, axisName = None):
return self.tk.call(self._w, 'x2axis', 'use', axisName)
def yaxis_cget(self, key):
return self.tk.call(self._w, 'yaxis', 'cget', '-' + key)
def yaxis_configure(self, option=None, **kw):
subcommand = (self._w, 'yaxis', 'configure')
return _doConfigure(self, subcommand, option, kw)
def yaxis_invtransform(self, value):
return self.tk.getdouble(self.tk.call(
self._w, 'yaxis', 'invtransform', value))
def yaxis_limits(self):
return self._getdoubles(self.tk.call(self._w, 'yaxis', 'limits'))
def yaxis_transform(self, value):
return self.tk.getint(self.tk.call(
self._w, 'yaxis', 'transform', value))
def yaxis_use(self, axisName = None):
return self.tk.call(self._w, 'yaxis', 'use', axisName)
def y2axis_cget(self, key):
return self.tk.call(self._w, 'y2axis', 'cget', '-' + key)
def y2axis_configure(self, option=None, **kw):
subcommand = (self._w, 'y2axis', 'configure')
return _doConfigure(self, subcommand, option, kw)
def y2axis_invtransform(self, value):
return self.tk.getdouble(self.tk.call(
self._w, 'y2axis', 'invtransform', value))
def y2axis_limits(self):
return self._getdoubles(self.tk.call(self._w, 'y2axis', 'limits'))
def y2axis_transform(self, value):
return self.tk.getint(self.tk.call(
self._w, 'y2axis', 'transform', value))
def y2axis_use(self, axisName = None):
return self.tk.call(self._w, 'y2axis', 'use', axisName)
def crosshairs_cget(self, key):
return self.tk.call(self._w, 'crosshairs', 'cget', '-' + key)
def crosshairs_configure(self, option=None, **kw):
subcommand = (self._w, 'crosshairs', 'configure')
return _doConfigure(self, subcommand, option, kw)
def crosshairs_off(self):
self.tk.call(self._w, 'crosshairs', 'off')
def crosshairs_on(self):
self.tk.call(self._w, 'crosshairs', 'on')
def crosshairs_toggle(self):
self.tk.call(self._w, 'crosshairs', 'toggle')
def element_activate(self, name, *args):
self.tk.call((self._w, 'element', 'activate', name) + args)
def element_bind(self, tagName, sequence=None, func=None, add=None):
return self._bind((self._w, 'element', 'bind', tagName),
sequence, func, add)
def element_unbind(self, tagName, sequence, funcid=None):
self.tk.call(self._w, 'element', 'bind', tagName, sequence, '')
if funcid:
self.deletecommand(funcid)
def element_cget(self, name, key):
return self.tk.call(self._w, 'element', 'cget', name, '-' + key)
def element_closest(self, x, y, *args, **kw):
var = 'python_private_1'
success = self.tk.getint(self.tk.call(
(self._w, 'element', 'closest', x, y, var) +
self._options(kw) + args))
if success:
rtn = {}
rtn['dist'] = self.tk.getdouble(self.tk.globalgetvar(var, 'dist'))
rtn['x'] = self.tk.getdouble(self.tk.globalgetvar(var, 'x'))
rtn['y'] = self.tk.getdouble(self.tk.globalgetvar(var, 'y'))
rtn['index'] = self.tk.getint(self.tk.globalgetvar(var, 'index'))
rtn['name'] = self.tk.globalgetvar(var, 'name')
return rtn
else:
return None
def element_configure(self, names, option=None, **kw):
# <names> may be a list of elemNames.
if type(names) == types.StringType:
names = [names]
subcommand = (self._w, 'element', 'configure') + tuple(names)
return _doConfigure(self, subcommand, option, kw)
def element_deactivate(self, *args):
self.tk.call((self._w, 'element', 'deactivate') + args)
def element_delete(self, *args):
self.tk.call((self._w, 'element', 'delete') + args)
def element_exists(self, name):
return self.tk.getboolean(
self.tk.call(self._w, 'element', 'exists', name))
def element_names(self, *args):
return self.tk.splitlist(
self.tk.call((self._w, 'element', 'names') + args))
def element_show(self, nameList=None):
if nameList is not None:
nameList = tuple(nameList)
return self.tk.splitlist(
self.tk.call(self._w, 'element', 'show', nameList))
def element_type(self, name):
return self.tk.call(self._w, 'element', 'type', name)
def grid_cget(self, key):
return self.tk.call(self._w, 'grid', 'cget', '-' + key)
def grid_configure(self, option=None, **kw):
subcommand = (self._w, 'grid', 'configure')
return _doConfigure(self, subcommand, option, kw)
def grid_off(self):
self.tk.call(self._w, 'grid', 'off')
def grid_on(self):
self.tk.call(self._w, 'grid', 'on')
def grid_toggle(self):
self.tk.call(self._w, 'grid', 'toggle')
def legend_activate(self, *args):
self.tk.call((self._w, 'legend', 'activate') + args)
def legend_bind(self, tagName, sequence=None, func=None, add=None):
return self._bind((self._w, 'legend', 'bind', tagName),
sequence, func, add)
def legend_unbind(self, tagName, sequence, funcid=None):
self.tk.call(self._w, 'legend', 'bind', tagName, sequence, '')
if funcid:
self.deletecommand(funcid)
def legend_cget(self, key):
return self.tk.call(self._w, 'legend', 'cget', '-' + key)
def legend_configure(self, option=None, **kw):
subcommand = (self._w, 'legend', 'configure')
return _doConfigure(self, subcommand, option, kw)
def legend_deactivate(self, *args):
self.tk.call((self._w, 'legend', 'deactivate') + args)
def legend_get(self, pos):
return self.tk.call(self._w, 'legend', 'get', pos)
def pen_cget(self, name, key):
return self.tk.call(self._w, 'pen', 'cget', name, '-' + key)
def pen_configure(self, names, option=None, **kw):
# <names> may be a list of penNames.
if type(names) == types.StringType:
names = [names]
subcommand = (self._w, 'pen', 'configure') + tuple(names)
return _doConfigure(self, subcommand, option, kw)
def pen_create(self, name, **kw):
self.tk.call((self._w, 'pen', 'create', name) + self._options(kw))
def pen_delete(self, *args):
self.tk.call((self._w, 'pen', 'delete') + args)
def pen_names(self, *args):
return self.tk.splitlist(self.tk.call((self._w, 'pen', 'names') + args))
def postscript_cget(self, key):
return self.tk.call(self._w, 'postscript', 'cget', '-' + key)
def postscript_configure(self, option=None, **kw):
subcommand = (self._w, 'postscript', 'configure')
return _doConfigure(self, subcommand, option, kw)
def postscript_output(self, fileName=None, **kw):
prefix = (self._w, 'postscript', 'output')
if fileName is None:
return self.tk.call(prefix + self._options(kw))
else:
self.tk.call(prefix + (fileName,) + self._options(kw))
def marker_after(self, first, second=None):
self.tk.call(self._w, 'marker', 'after', first, second)
def marker_before(self, first, second=None):
self.tk.call(self._w, 'marker', 'before', first, second)
def marker_bind(self, tagName, sequence=None, func=None, add=None):
return self._bind((self._w, 'marker', 'bind', tagName),
sequence, func, add)
def marker_unbind(self, tagName, sequence, funcid=None):
self.tk.call(self._w, 'marker', 'bind', tagName, sequence, '')
if funcid:
self.deletecommand(funcid)
def marker_cget(self, name, key):
return self.tk.call(self._w, 'marker', 'cget', name, '-' + key)
def marker_configure(self, names, option=None, **kw):
# <names> may be a list of markerIds.
if type(names) == types.StringType:
names = [names]
subcommand = (self._w, 'marker', 'configure') + tuple(names)
return _doConfigure(self, subcommand, option, kw)
def marker_create(self, type, **kw):
return self.tk.call(
(self._w, 'marker', 'create', type) + self._options(kw))
def marker_delete(self, *args):
self.tk.call((self._w, 'marker', 'delete') + args)
def marker_exists(self, name):
return self.tk.getboolean(
self.tk.call(self._w, 'marker', 'exists', name))
def marker_names(self, *args):
return self.tk.splitlist(
self.tk.call((self._w, 'marker', 'names') + args))
def marker_type(self, name):
type = self.tk.call(self._w, 'marker', 'type', name)
if type == '':
type = None
return type
#=============================================================================
class Stripchart(Graph):
# Wrapper for the blt stripchart widget, version 2.4.
def __init__(self, master=None, cnf={}, **kw):
_loadBlt(master)
Tkinter.Widget.__init__(self, master, _chartCommand, cnf, kw)
#=============================================================================
class Tabset(Tkinter.Widget):
# Wrapper for the blt TabSet widget, version 2.4.
def __init__(self, master=None, cnf={}, **kw):
_loadBlt(master)
Tkinter.Widget.__init__(self, master, _tabsetCommand, cnf, kw)
def activate(self, tabIndex):
self.tk.call(self._w, 'activate', tabIndex)
# This is the 'bind' sub-command:
def tag_bind(self, tagName, sequence=None, func=None, add=None):
return self._bind((self._w, 'bind', tagName), sequence, func, add)
def tag_unbind(self, tagName, sequence, funcid=None):
self.tk.call(self._w, 'bind', tagName, sequence, '')
if funcid:
self.deletecommand(funcid)
def delete(self, first, last = None):
self.tk.call(self._w, 'delete', first, last)
# This is the 'focus' sub-command:
def tab_focus(self, tabIndex):
self.tk.call(self._w, 'focus', tabIndex)
def get(self, tabIndex):
return self.tk.call(self._w, 'get', tabIndex)
def index(self, tabIndex):
index = self.tk.call(self._w, 'index', tabIndex)
if index == '':
return None
else:
return self.tk.getint(self.tk.call(self._w, 'index', tabIndex))
def insert(self, position, name1, *names, **kw):
self.tk.call(
(self._w, 'insert', position, name1) + names + self._options(kw))
def invoke(self, tabIndex):
return self.tk.call(self._w, 'invoke', tabIndex)
def move(self, tabIndex1, beforeOrAfter, tabIndex2):
self.tk.call(self._w, 'move', tabIndex1, beforeOrAfter, tabIndex2)
def nearest(self, x, y):
return self.tk.call(self._w, 'nearest', x, y)
def scan_mark(self, x, y):
self.tk.call(self._w, 'scan', 'mark', x, y)
def scan_dragto(self, x, y):
self.tk.call(self._w, 'scan', 'dragto', x, y)
def see(self, index):
self.tk.call(self._w, 'see', index)
def see(self, tabIndex):
self.tk.call(self._w,'see',tabIndex)
def size(self):
return self.tk.getint(self.tk.call(self._w, 'size'))
def tab_cget(self, tabIndex, option):
if option[:1] != '-':
option = '-' + option
if option[-1:] == '_':
option = option[:-1]
return self.tk.call(self._w, 'tab', 'cget', tabIndex, option)
def tab_configure(self, tabIndexes, option=None, **kw):
# <tabIndexes> may be a list of tabs.
if type(tabIndexes) in (types.StringType, types.IntType):
tabIndexes = [tabIndexes]
subcommand = (self._w, 'tab', 'configure') + tuple(tabIndexes)
return _doConfigure(self, subcommand, option, kw)
def tab_names(self, *args):
return self.tk.splitlist(self.tk.call((self._w, 'tab', 'names') + args))
def tab_tearoff(self, tabIndex, newName = None):
if newName is None:
name = self.tk.call(self._w, 'tab', 'tearoff', tabIndex)
return self.nametowidget(name)
else:
self.tk.call(self._w, 'tab', 'tearoff', tabIndex, newName)
def view(self):
s = self.tk.call(self._w, 'view')
return tuple(map(self.tk.getint, self.tk.splitlist(s)))
def view_moveto(self, fraction):
self.tk.call(self._w, 'view', 'moveto', fraction)
def view_scroll(self, number, what):
self.tk.call(self._w, 'view', 'scroll', number, what)
--- NEW FILE: PmwButtonBox.py ---
# Based on iwidgets2.2.0/buttonbox.itk code.
import types
import Tkinter
import Pmw
class ButtonBox(Pmw.MegaWidget):
def __init__(self, parent = None, **kw):
# Define the megawidget options.
INITOPT = Pmw.INITOPT
optiondefs = (
('labelmargin', 0, INITOPT),
('labelpos', None, INITOPT),
('orient', 'horizontal', INITOPT),
('padx', 3, INITOPT),
('pady', 3, INITOPT),
)
self.defineoptions(kw, optiondefs, dynamicGroups = ('Button',))
# Initialise the base class (after defining the options).
Pmw.MegaWidget.__init__(self, parent)
# Create the components.
interior = self.interior()
if self['labelpos'] is None:
self._buttonBoxFrame = self._hull
columnOrRow = 0
else:
self._buttonBoxFrame = self.createcomponent('frame',
(), None,
Tkinter.Frame, (interior,))
self._buttonBoxFrame.grid(column=2, row=2, sticky='nsew')
columnOrRow = 2
self.createlabel(interior)
orient = self['orient']
if orient == 'horizontal':
interior.grid_columnconfigure(columnOrRow, weight = 1)
elif orient == 'vertical':
interior.grid_rowconfigure(columnOrRow, weight = 1)
else:
raise ValueError, 'bad orient option ' + repr(orient) + \
': must be either \'horizontal\' or \'vertical\''
# Initialise instance variables.
# List of tuples describing the buttons:
# - name
# - button widget
self._buttonList = []
# The index of the default button.
self._defaultButton = None
self._timerId = None
# Check keywords and initialise options.
self.initialiseoptions()
def destroy(self):
if self._timerId:
self.after_cancel(self._timerId)
self._timerId = None
Pmw.MegaWidget.destroy(self)
def numbuttons(self):
return len(self._buttonList)
def index(self, index, forInsert = 0):
listLength = len(self._buttonList)
if type(index) == types.IntType:
if forInsert and index <= listLength:
return index
elif not forInsert and index < listLength:
return index
else:
raise ValueError, 'index "%s" is out of range' % index
elif index is Pmw.END:
if forInsert:
return listLength
elif listLength > 0:
return listLength - 1
else:
raise ValueError, 'ButtonBox has no buttons'
elif index is Pmw.DEFAULT:
if self._defaultButton is not None:
return self._defaultButton
raise ValueError, 'ButtonBox has no default'
else:
names = map(lambda t: t[0], self._buttonList)
if index in names:
return names.index(index)
validValues = 'a name, a number, Pmw.END or Pmw.DEFAULT'
raise ValueError, \
'bad index "%s": must be %s' % (index, validValues)
def insert(self, componentName, beforeComponent = 0, **kw):
if componentName in self.components():
raise ValueError, 'button "%s" already exists' % componentName
if not kw.has_key('text'):
kw['text'] = componentName
kw['default'] = 'normal'
button = apply(self.createcomponent, (componentName,
(), 'Button',
Tkinter.Button, (self._buttonBoxFrame,)), kw)
index = self.index(beforeComponent, 1)
horizontal = self['orient'] == 'horizontal'
numButtons = len(self._buttonList)
# Shift buttons up one position.
for i in range(numButtons - 1, index - 1, -1):
widget = self._buttonList[i][1]
pos = i * 2 + 3
if horizontal:
widget.grid(column = pos, row = 0)
else:
widget.grid(column = 0, row = pos)
# Display the new button.
if horizontal:
button.grid(column = index * 2 + 1, row = 0, sticky = 'ew',
padx = self['padx'], pady = self['pady'])
self._buttonBoxFrame.grid_columnconfigure(
numButtons * 2 + 2, weight = 1)
else:
button.grid(column = 0, row = index * 2 + 1, sticky = 'ew',
padx = self['padx'], pady = self['pady'])
self._buttonBoxFrame.grid_rowconfigure(
numButtons * 2 + 2, weight = 1)
self._buttonList.insert(index, (componentName, button))
return button
def add(self, componentName, **kw):
return apply(self.insert, (componentName, len(self._buttonList)), kw)
def delete(self, index):
index = self.index(index)
(name, widget) = self._buttonList[index]
widget.grid_forget()
self.destroycomponent(name)
numButtons = len(self._buttonList)
# Shift buttons down one position.
horizontal = self['orient'] == 'horizontal'
for i in range(index + 1, numButtons):
widget = self._buttonList[i][1]
pos = i * 2 - 1
if horizontal:
widget.grid(column = pos, row = 0)
else:
widget.grid(column = 0, row = pos)
if horizontal:
self._buttonBoxFrame.grid_columnconfigure(numButtons * 2 - 1,
minsize = 0)
self._buttonBoxFrame.grid_columnconfigure(numButtons * 2, weight = 0)
else:
self._buttonBoxFrame.grid_rowconfigure(numButtons * 2, weight = 0)
del self._buttonList[index]
def setdefault(self, index):
# Turn off the default ring around the current default button.
if self._defaultButton is not None:
button = self._buttonList[self._defaultButton][1]
button.configure(default = 'normal')
self._defaultButton = None
# Turn on the default ring around the new default button.
if index is not None:
index = self.index(index)
self._defaultButton = index
button = self._buttonList[index][1]
button.configure(default = 'active')
def invoke(self, index = Pmw.DEFAULT, noFlash = 0):
# Invoke the callback associated with the *index* button. If
# *noFlash* is not set, flash the button to indicate to the
# user that something happened.
button = self._buttonList[self.index(index)][1]
if not noFlash:
state = button.cget('state')
relief = button.cget('relief')
button.configure(state = 'active', relief = 'sunken')
self.update_idletasks()
self.after(100)
button.configure(state = state, relief = relief)
return button.invoke()
def button(self, buttonIndex):
return self._buttonList[self.index(buttonIndex)][1]
def alignbuttons(self, when = 'later'):
if when == 'later':
if not self._timerId:
self._timerId = self.after_idle(self.alignbuttons, 'now')
return
self.update_idletasks()
self._timerId = None
# Determine the width of the maximum length button.
max = 0
horizontal = (self['orient'] == 'horizontal')
for index in range(len(self._buttonList)):
gridIndex = index * 2 + 1
if horizontal:
width = self._buttonBoxFrame.grid_bbox(gridIndex, 0)[2]
else:
width = self._buttonBoxFrame.grid_bbox(0, gridIndex)[2]
if width > max:
max = width
# Set the width of all the buttons to be the same.
if horizontal:
for index in range(len(self._buttonList)):
self._buttonBoxFrame.grid_columnconfigure(index * 2 + 1,
minsize = max)
else:
self._buttonBoxFrame.grid_columnconfigure(0, minsize = max)
--- NEW FILE: PmwColor.py ---
# Functions for converting colors and modifying the color scheme of
# an application.
import math
import string
import sys
import Tkinter
_PI = math.pi
_TWO_PI = _PI * 2
_THIRD_PI = _PI / 3
_SIXTH_PI = _PI / 6
_MAX_RGB = float(256 * 256 - 1) # max size of rgb values returned from Tk
def setscheme(root, background=None, **kw):
root = root._root()
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
# from a few widgets.
ckbtn = Tkinter.Checkbutton(root)
entry = Tkinter.Entry(root)
scbar = Tkinter.Scrollbar(root)
orig = {}
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])
ckbtn.destroy()
entry.destroy()
scbar.destroy()
return orig
#======================================================================
# 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
# required brightness.
rgb = name2rgb(root, colorName)
hue, saturation, intensity = rgb2hsi(rgb)
if saturation == 0.0:
hue = None
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.
if hue is None:
rgb = hsi2rgb(0.0, 0.0, brightness)
else:
while hue < 0:
hue = hue + _TWO_PI
while hue >= _TWO_PI:
hue = hue - _TWO_PI
rgb = hsi2rgb(hue, 1.0, 1.0)
if brightness is not None:
b = rgb2brightness(rgb)
i = 1.0 - (1.0 - brightness) * b
s = bhi2saturation(brightness, hue, i)
rgb = hsi2rgb(hue, s, i)
return rgb2name(rgb)
def bhi2saturation(brightness, hue, intensity):
while hue < 0:
hue = hue + _TWO_PI
while hue >= _TWO_PI:
hue = hue - _TWO_PI
hue = hue / _THIRD_PI
f = hue - math.floor(hue)
pp = intensity
pq = intensity * f
pt = intensity - intensity * f
pv = 0
hue = int(hue)
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):
i = intensity
if saturation == 0:
rgb = [i, i, i]
else:
while hue < 0:
hue = hue + _TWO_PI
while hue >= _TWO_PI:
hue = hue - _TWO_PI
hue = hue / _THIRD_PI
f = hue - math.floor(hue)
p = i * (1.0 - saturation)
q = i * (1.0 - saturation * f)
t = i * (1.0 - saturation * (1.0 - f))
hue = int(hue)
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]
for index in range(3):
val = rgb[index]
if val < 0.0:
val = 0.0
if val > 1.0:
val = 1.0
rgb[index] = val
return rgb
def average(rgb1, rgb2, fraction):
return (
rgb2[0] * fraction + rgb1[0] * (1.0 - fraction),
rgb2[1] * fraction + rgb1[1] * (1.0 - fraction),
rgb2[2] * fraction + rgb1[2] * (1.0 - fraction)
)
def rgb2name(rgb):
return '#%02x%02x%02x' % \
(int(rgb[0] * 255), int(rgb[1] * 255), int(rgb[2] * 255))
def rgb2brightness(rgb):
# Return the perceived grey level of the color
# (0.0 == black, 1.0 == white).
rf = 0.299
gf = 0.587
bf = 0.114
return rf * rgb[0] + gf * rgb[1] + bf * rgb[2]
def rgb2hsi(rgb):
maxc = max(rgb[0], rgb[1], rgb[2])
minc = min(rgb[0], rgb[1], rgb[2])
intensity = maxc
if maxc != 0:
saturation = (maxc - minc) / maxc
else:
saturation = 0.0
hue = 0.0
if saturation != 0.0:
c = []
for index in range(3):
c.append((maxc - rgb[index]) / (maxc - minc))
if rgb[0] == maxc:
hue = c[2] - c[1]
elif rgb[1] == maxc:
hue = 2 + c[0] - c[2]
elif rgb[2] == maxc:
hue = 4 + c[1] - c[0]
hue = hue * _THIRD_PI
if hue < 0.0:
hue = hue + _TWO_PI
return (hue, saturation, intensity)
def name2rgb(root, colorName, asInt = 0):
if colorName[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)
rgb = (
string.atoi(colorName[0:digits], 16) * factor,
string.atoi(colorName[digits:digits * 2], 16) * factor,
string.atoi(colorName[digits * 2:digits * 3], 16) * factor,
)
else:
# We have no choice but to ask Tk what the rgb values are.
rgb = root.winfo_rgb(colorName)
if not asInt:
rgb = (rgb[0] / _MAX_RGB, rgb[1] / _MAX_RGB, rgb[2] / _MAX_RGB)
return 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.
new = {}
for key, value in kw.items():
new[key] = value
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',
'highlightColor'):
if not new.has_key(i):
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.
lighterBg = []
for i in range(3):
lighterBg.append(bg[i])
inc1 = lighterBg[i] * 0.09
inc2 = (1.0 - lighterBg[i]) / 3
if inc1 > inc2:
lighterBg[i] = lighterBg[i] + inc1
else:
lighterBg[i] = lighterBg[i] + inc2
if lighterBg[i] > 1.0:
lighterBg[i] = 1.0
# Set <darkerBg> to a color that is a little darker that the
# normal background.
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)
else:
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'
return new
def spectrum(numColors, correction = 1.0, saturation = 1.0, intensity = 1.0,
extraOrange = 1, returnHues = 0):
colorList = []
division = numColors / 7.0
for index in range(numColors):
if extraOrange:
if index < 2 * division:
hue = index / division
else:
hue = 2 + 2 * (index - 2 * division) / division
hue = hue * _SIXTH_PI
else:
hue = index * _TWO_PI / numColors
if returnHues:
colorList.append(hue)
else:
rgb = hsi2rgb(hue, saturation, intensity)
if correction != 1.0:
rgb = correct(rgb, correction)
name = rgb2name(rgb)
colorList.append(name)
return colorList
def correct(rgb, correction):
correction = float(correction)
rtn = []
for index in range(3):
rtn.append((1 - (1 - rgb[index]) ** correction) ** (1 / correction))
return rtn
#==============================================================================
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)
try:
value = str(widget.cget(option))
except:
continue
if oldpalette is None or value == oldpalett...
[truncated message content] |