mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-22 21:32:31 +00:00
python-3.6.zip added from Github
README.cosmo contains the necessary links.
This commit is contained in:
parent
75fc601ff5
commit
0c4c56ff39
4219 changed files with 1968626 additions and 0 deletions
130
third_party/python/Tools/pynche/ChipViewer.py
vendored
Normal file
130
third_party/python/Tools/pynche/ChipViewer.py
vendored
Normal file
|
@ -0,0 +1,130 @@
|
|||
"""Chip viewer and widget.
|
||||
|
||||
In the lower left corner of the main Pynche window, you will see two
|
||||
ChipWidgets, one for the selected color and one for the nearest color. The
|
||||
selected color is the actual RGB value expressed as an X11 #COLOR name. The
|
||||
nearest color is the named color from the X11 database that is closest to the
|
||||
selected color in 3D space. There may be other colors equally close, but the
|
||||
nearest one is the first one found.
|
||||
|
||||
Clicking on the nearest color chip selects that named color.
|
||||
|
||||
The ChipViewer class includes the entire lower left quandrant; i.e. both the
|
||||
selected and nearest ChipWidgets.
|
||||
"""
|
||||
|
||||
from tkinter import *
|
||||
import ColorDB
|
||||
|
||||
|
||||
class ChipWidget:
|
||||
_WIDTH = 150
|
||||
_HEIGHT = 80
|
||||
|
||||
def __init__(self,
|
||||
master = None,
|
||||
width = _WIDTH,
|
||||
height = _HEIGHT,
|
||||
text = 'Color',
|
||||
initialcolor = 'blue',
|
||||
presscmd = None,
|
||||
releasecmd = None):
|
||||
# create the text label
|
||||
self.__label = Label(master, text=text)
|
||||
self.__label.grid(row=0, column=0)
|
||||
# create the color chip, implemented as a frame
|
||||
self.__chip = Frame(master, relief=RAISED, borderwidth=2,
|
||||
width=width,
|
||||
height=height,
|
||||
background=initialcolor)
|
||||
self.__chip.grid(row=1, column=0)
|
||||
# create the color name
|
||||
self.__namevar = StringVar()
|
||||
self.__namevar.set(initialcolor)
|
||||
self.__name = Entry(master, textvariable=self.__namevar,
|
||||
relief=FLAT, justify=CENTER, state=DISABLED,
|
||||
font=self.__label['font'])
|
||||
self.__name.grid(row=2, column=0)
|
||||
# create the message area
|
||||
self.__msgvar = StringVar()
|
||||
self.__name = Entry(master, textvariable=self.__msgvar,
|
||||
relief=FLAT, justify=CENTER, state=DISABLED,
|
||||
font=self.__label['font'])
|
||||
self.__name.grid(row=3, column=0)
|
||||
# set bindings
|
||||
if presscmd:
|
||||
self.__chip.bind('<ButtonPress-1>', presscmd)
|
||||
if releasecmd:
|
||||
self.__chip.bind('<ButtonRelease-1>', releasecmd)
|
||||
|
||||
def set_color(self, color):
|
||||
self.__chip.config(background=color)
|
||||
|
||||
def get_color(self):
|
||||
return self.__chip['background']
|
||||
|
||||
def set_name(self, colorname):
|
||||
self.__namevar.set(colorname)
|
||||
|
||||
def set_message(self, message):
|
||||
self.__msgvar.set(message)
|
||||
|
||||
def press(self):
|
||||
self.__chip.configure(relief=SUNKEN)
|
||||
|
||||
def release(self):
|
||||
self.__chip.configure(relief=RAISED)
|
||||
|
||||
|
||||
|
||||
class ChipViewer:
|
||||
def __init__(self, switchboard, master=None):
|
||||
self.__sb = switchboard
|
||||
self.__frame = Frame(master, relief=RAISED, borderwidth=1)
|
||||
self.__frame.grid(row=3, column=0, ipadx=5, sticky='NSEW')
|
||||
# create the chip that will display the currently selected color
|
||||
# exactly
|
||||
self.__sframe = Frame(self.__frame)
|
||||
self.__sframe.grid(row=0, column=0)
|
||||
self.__selected = ChipWidget(self.__sframe, text='Selected')
|
||||
# create the chip that will display the nearest real X11 color
|
||||
# database color name
|
||||
self.__nframe = Frame(self.__frame)
|
||||
self.__nframe.grid(row=0, column=1)
|
||||
self.__nearest = ChipWidget(self.__nframe, text='Nearest',
|
||||
presscmd = self.__buttonpress,
|
||||
releasecmd = self.__buttonrelease)
|
||||
|
||||
def update_yourself(self, red, green, blue):
|
||||
# Selected always shows the #rrggbb name of the color, nearest always
|
||||
# shows the name of the nearest color in the database. BAW: should
|
||||
# an exact match be indicated in some way?
|
||||
#
|
||||
# Always use the #rrggbb style to actually set the color, since we may
|
||||
# not be using X color names (e.g. "web-safe" names)
|
||||
colordb = self.__sb.colordb()
|
||||
rgbtuple = (red, green, blue)
|
||||
rrggbb = ColorDB.triplet_to_rrggbb(rgbtuple)
|
||||
# find the nearest
|
||||
nearest = colordb.nearest(red, green, blue)
|
||||
nearest_tuple = colordb.find_byname(nearest)
|
||||
nearest_rrggbb = ColorDB.triplet_to_rrggbb(nearest_tuple)
|
||||
self.__selected.set_color(rrggbb)
|
||||
self.__nearest.set_color(nearest_rrggbb)
|
||||
# set the name and messages areas
|
||||
self.__selected.set_name(rrggbb)
|
||||
if rrggbb == nearest_rrggbb:
|
||||
self.__selected.set_message(nearest)
|
||||
else:
|
||||
self.__selected.set_message('')
|
||||
self.__nearest.set_name(nearest_rrggbb)
|
||||
self.__nearest.set_message(nearest)
|
||||
|
||||
def __buttonpress(self, event=None):
|
||||
self.__nearest.press()
|
||||
|
||||
def __buttonrelease(self, event=None):
|
||||
self.__nearest.release()
|
||||
rrggbb = self.__nearest.get_color()
|
||||
red, green, blue = ColorDB.rrggbb_to_triplet(rrggbb)
|
||||
self.__sb.update_views(red, green, blue)
|
271
third_party/python/Tools/pynche/ColorDB.py
vendored
Normal file
271
third_party/python/Tools/pynche/ColorDB.py
vendored
Normal file
|
@ -0,0 +1,271 @@
|
|||
"""Color Database.
|
||||
|
||||
This file contains one class, called ColorDB, and several utility functions.
|
||||
The class must be instantiated by the get_colordb() function in this file,
|
||||
passing it a filename to read a database out of.
|
||||
|
||||
The get_colordb() function will try to examine the file to figure out what the
|
||||
format of the file is. If it can't figure out the file format, or it has
|
||||
trouble reading the file, None is returned. You can pass get_colordb() an
|
||||
optional filetype argument.
|
||||
|
||||
Supporte file types are:
|
||||
|
||||
X_RGB_TXT -- X Consortium rgb.txt format files. Three columns of numbers
|
||||
from 0 .. 255 separated by whitespace. Arbitrary trailing
|
||||
columns used as the color name.
|
||||
|
||||
The utility functions are useful for converting between the various expected
|
||||
color formats, and for calculating other color values.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
from types import *
|
||||
|
||||
class BadColor(Exception):
|
||||
pass
|
||||
|
||||
DEFAULT_DB = None
|
||||
SPACE = ' '
|
||||
COMMASPACE = ', '
|
||||
|
||||
|
||||
|
||||
# generic class
|
||||
class ColorDB:
|
||||
def __init__(self, fp):
|
||||
lineno = 2
|
||||
self.__name = fp.name
|
||||
# Maintain several dictionaries for indexing into the color database.
|
||||
# Note that while Tk supports RGB intensities of 4, 8, 12, or 16 bits,
|
||||
# for now we only support 8 bit intensities. At least on OpenWindows,
|
||||
# all intensities in the /usr/openwin/lib/rgb.txt file are 8-bit
|
||||
#
|
||||
# key is (red, green, blue) tuple, value is (name, [aliases])
|
||||
self.__byrgb = {}
|
||||
# key is name, value is (red, green, blue)
|
||||
self.__byname = {}
|
||||
# all unique names (non-aliases). built-on demand
|
||||
self.__allnames = None
|
||||
for line in fp:
|
||||
# get this compiled regular expression from derived class
|
||||
mo = self._re.match(line)
|
||||
if not mo:
|
||||
print('Error in', fp.name, ' line', lineno, file=sys.stderr)
|
||||
lineno += 1
|
||||
continue
|
||||
# extract the red, green, blue, and name
|
||||
red, green, blue = self._extractrgb(mo)
|
||||
name = self._extractname(mo)
|
||||
keyname = name.lower()
|
||||
# BAW: for now the `name' is just the first named color with the
|
||||
# rgb values we find. Later, we might want to make the two word
|
||||
# version the `name', or the CapitalizedVersion, etc.
|
||||
key = (red, green, blue)
|
||||
foundname, aliases = self.__byrgb.get(key, (name, []))
|
||||
if foundname != name and foundname not in aliases:
|
||||
aliases.append(name)
|
||||
self.__byrgb[key] = (foundname, aliases)
|
||||
# add to byname lookup
|
||||
self.__byname[keyname] = key
|
||||
lineno = lineno + 1
|
||||
|
||||
# override in derived classes
|
||||
def _extractrgb(self, mo):
|
||||
return [int(x) for x in mo.group('red', 'green', 'blue')]
|
||||
|
||||
def _extractname(self, mo):
|
||||
return mo.group('name')
|
||||
|
||||
def filename(self):
|
||||
return self.__name
|
||||
|
||||
def find_byrgb(self, rgbtuple):
|
||||
"""Return name for rgbtuple"""
|
||||
try:
|
||||
return self.__byrgb[rgbtuple]
|
||||
except KeyError:
|
||||
raise BadColor(rgbtuple)
|
||||
|
||||
def find_byname(self, name):
|
||||
"""Return (red, green, blue) for name"""
|
||||
name = name.lower()
|
||||
try:
|
||||
return self.__byname[name]
|
||||
except KeyError:
|
||||
raise BadColor(name)
|
||||
|
||||
def nearest(self, red, green, blue):
|
||||
"""Return the name of color nearest (red, green, blue)"""
|
||||
# BAW: should we use Voronoi diagrams, Delaunay triangulation, or
|
||||
# octree for speeding up the locating of nearest point? Exhaustive
|
||||
# search is inefficient, but seems fast enough.
|
||||
nearest = -1
|
||||
nearest_name = ''
|
||||
for name, aliases in self.__byrgb.values():
|
||||
r, g, b = self.__byname[name.lower()]
|
||||
rdelta = red - r
|
||||
gdelta = green - g
|
||||
bdelta = blue - b
|
||||
distance = rdelta * rdelta + gdelta * gdelta + bdelta * bdelta
|
||||
if nearest == -1 or distance < nearest:
|
||||
nearest = distance
|
||||
nearest_name = name
|
||||
return nearest_name
|
||||
|
||||
def unique_names(self):
|
||||
# sorted
|
||||
if not self.__allnames:
|
||||
self.__allnames = []
|
||||
for name, aliases in self.__byrgb.values():
|
||||
self.__allnames.append(name)
|
||||
self.__allnames.sort(key=str.lower)
|
||||
return self.__allnames
|
||||
|
||||
def aliases_of(self, red, green, blue):
|
||||
try:
|
||||
name, aliases = self.__byrgb[(red, green, blue)]
|
||||
except KeyError:
|
||||
raise BadColor((red, green, blue))
|
||||
return [name] + aliases
|
||||
|
||||
|
||||
class RGBColorDB(ColorDB):
|
||||
_re = re.compile(
|
||||
r'\s*(?P<red>\d+)\s+(?P<green>\d+)\s+(?P<blue>\d+)\s+(?P<name>.*)')
|
||||
|
||||
|
||||
class HTML40DB(ColorDB):
|
||||
_re = re.compile(r'(?P<name>\S+)\s+(?P<hexrgb>#[0-9a-fA-F]{6})')
|
||||
|
||||
def _extractrgb(self, mo):
|
||||
return rrggbb_to_triplet(mo.group('hexrgb'))
|
||||
|
||||
class LightlinkDB(HTML40DB):
|
||||
_re = re.compile(r'(?P<name>(.+))\s+(?P<hexrgb>#[0-9a-fA-F]{6})')
|
||||
|
||||
def _extractname(self, mo):
|
||||
return mo.group('name').strip()
|
||||
|
||||
class WebsafeDB(ColorDB):
|
||||
_re = re.compile('(?P<hexrgb>#[0-9a-fA-F]{6})')
|
||||
|
||||
def _extractrgb(self, mo):
|
||||
return rrggbb_to_triplet(mo.group('hexrgb'))
|
||||
|
||||
def _extractname(self, mo):
|
||||
return mo.group('hexrgb').upper()
|
||||
|
||||
|
||||
|
||||
# format is a tuple (RE, SCANLINES, CLASS) where RE is a compiled regular
|
||||
# expression, SCANLINES is the number of header lines to scan, and CLASS is
|
||||
# the class to instantiate if a match is found
|
||||
|
||||
FILETYPES = [
|
||||
(re.compile('Xorg'), RGBColorDB),
|
||||
(re.compile('XConsortium'), RGBColorDB),
|
||||
(re.compile('HTML'), HTML40DB),
|
||||
(re.compile('lightlink'), LightlinkDB),
|
||||
(re.compile('Websafe'), WebsafeDB),
|
||||
]
|
||||
|
||||
def get_colordb(file, filetype=None):
|
||||
colordb = None
|
||||
fp = open(file)
|
||||
try:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
return None
|
||||
# try to determine the type of RGB file it is
|
||||
if filetype is None:
|
||||
filetypes = FILETYPES
|
||||
else:
|
||||
filetypes = [filetype]
|
||||
for typere, class_ in filetypes:
|
||||
mo = typere.search(line)
|
||||
if mo:
|
||||
break
|
||||
else:
|
||||
# no matching type
|
||||
return None
|
||||
# we know the type and the class to grok the type, so suck it in
|
||||
colordb = class_(fp)
|
||||
finally:
|
||||
fp.close()
|
||||
# save a global copy
|
||||
global DEFAULT_DB
|
||||
DEFAULT_DB = colordb
|
||||
return colordb
|
||||
|
||||
|
||||
|
||||
_namedict = {}
|
||||
|
||||
def rrggbb_to_triplet(color):
|
||||
"""Converts a #rrggbb color to the tuple (red, green, blue)."""
|
||||
rgbtuple = _namedict.get(color)
|
||||
if rgbtuple is None:
|
||||
if color[0] != '#':
|
||||
raise BadColor(color)
|
||||
red = color[1:3]
|
||||
green = color[3:5]
|
||||
blue = color[5:7]
|
||||
rgbtuple = int(red, 16), int(green, 16), int(blue, 16)
|
||||
_namedict[color] = rgbtuple
|
||||
return rgbtuple
|
||||
|
||||
|
||||
_tripdict = {}
|
||||
def triplet_to_rrggbb(rgbtuple):
|
||||
"""Converts a (red, green, blue) tuple to #rrggbb."""
|
||||
global _tripdict
|
||||
hexname = _tripdict.get(rgbtuple)
|
||||
if hexname is None:
|
||||
hexname = '#%02x%02x%02x' % rgbtuple
|
||||
_tripdict[rgbtuple] = hexname
|
||||
return hexname
|
||||
|
||||
|
||||
def triplet_to_fractional_rgb(rgbtuple):
|
||||
return [x / 256 for x in rgbtuple]
|
||||
|
||||
|
||||
def triplet_to_brightness(rgbtuple):
|
||||
# return the brightness (grey level) along the scale 0.0==black to
|
||||
# 1.0==white
|
||||
r = 0.299
|
||||
g = 0.587
|
||||
b = 0.114
|
||||
return r*rgbtuple[0] + g*rgbtuple[1] + b*rgbtuple[2]
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
colordb = get_colordb('/usr/openwin/lib/rgb.txt')
|
||||
if not colordb:
|
||||
print('No parseable color database found')
|
||||
sys.exit(1)
|
||||
# on my system, this color matches exactly
|
||||
target = 'navy'
|
||||
red, green, blue = rgbtuple = colordb.find_byname(target)
|
||||
print(target, ':', red, green, blue, triplet_to_rrggbb(rgbtuple))
|
||||
name, aliases = colordb.find_byrgb(rgbtuple)
|
||||
print('name:', name, 'aliases:', COMMASPACE.join(aliases))
|
||||
r, g, b = (1, 1, 128) # nearest to navy
|
||||
r, g, b = (145, 238, 144) # nearest to lightgreen
|
||||
r, g, b = (255, 251, 250) # snow
|
||||
print('finding nearest to', target, '...')
|
||||
import time
|
||||
t0 = time.time()
|
||||
nearest = colordb.nearest(r, g, b)
|
||||
t1 = time.time()
|
||||
print('found nearest color', nearest, 'in', t1-t0, 'seconds')
|
||||
# dump the database
|
||||
for n in colordb.unique_names():
|
||||
r, g, b = colordb.find_byname(n)
|
||||
aliases = colordb.aliases_of(r, g, b)
|
||||
print('%20s: (%3d/%3d/%3d) == %s' % (n, r, g, b,
|
||||
SPACE.join(aliases[1:])))
|
273
third_party/python/Tools/pynche/DetailsViewer.py
vendored
Normal file
273
third_party/python/Tools/pynche/DetailsViewer.py
vendored
Normal file
|
@ -0,0 +1,273 @@
|
|||
"""DetailsViewer class.
|
||||
|
||||
This class implements a pure input window which allows you to meticulously
|
||||
edit the current color. You have both mouse control of the color (via the
|
||||
buttons along the bottom row), and there are keyboard bindings for each of the
|
||||
increment/decrement buttons.
|
||||
|
||||
The top three check buttons allow you to specify which of the three color
|
||||
variations are tied together when incrementing and decrementing. Red, green,
|
||||
and blue are self evident. By tying together red and green, you can modify
|
||||
the yellow level of the color. By tying together red and blue, you can modify
|
||||
the magenta level of the color. By tying together green and blue, you can
|
||||
modify the cyan level, and by tying all three together, you can modify the
|
||||
grey level.
|
||||
|
||||
The behavior at the boundaries (0 and 255) are defined by the `At boundary'
|
||||
option menu:
|
||||
|
||||
Stop
|
||||
When the increment or decrement would send any of the tied variations
|
||||
out of bounds, the entire delta is discarded.
|
||||
|
||||
Wrap Around
|
||||
When the increment or decrement would send any of the tied variations
|
||||
out of bounds, the out of bounds variation is wrapped around to the
|
||||
other side. Thus if red were at 238 and 25 were added to it, red
|
||||
would have the value 7.
|
||||
|
||||
Preserve Distance
|
||||
When the increment or decrement would send any of the tied variations
|
||||
out of bounds, all tied variations are wrapped as one, so as to
|
||||
preserve the distance between them. Thus if green and blue were tied,
|
||||
and green was at 238 while blue was at 223, and an increment of 25
|
||||
were applied, green would be at 15 and blue would be at 0.
|
||||
|
||||
Squash
|
||||
When the increment or decrement would send any of the tied variations
|
||||
out of bounds, the out of bounds variation is set to the ceiling of
|
||||
255 or floor of 0, as appropriate. In this way, all tied variations
|
||||
are squashed to one edge or the other.
|
||||
|
||||
The following key bindings can be used as accelerators. Note that Pynche can
|
||||
fall behind if you hold the key down as a key repeat:
|
||||
|
||||
Left arrow == -1
|
||||
Right arrow == +1
|
||||
|
||||
Control + Left == -10
|
||||
Control + Right == 10
|
||||
|
||||
Shift + Left == -25
|
||||
Shift + Right == +25
|
||||
"""
|
||||
|
||||
from tkinter import *
|
||||
|
||||
STOP = 'Stop'
|
||||
WRAP = 'Wrap Around'
|
||||
RATIO = 'Preserve Distance'
|
||||
GRAV = 'Squash'
|
||||
|
||||
ADDTOVIEW = 'Details Window...'
|
||||
|
||||
|
||||
class DetailsViewer:
|
||||
def __init__(self, switchboard, master=None):
|
||||
self.__sb = switchboard
|
||||
optiondb = switchboard.optiondb()
|
||||
self.__red, self.__green, self.__blue = switchboard.current_rgb()
|
||||
# GUI
|
||||
root = self.__root = Toplevel(master, class_='Pynche')
|
||||
root.protocol('WM_DELETE_WINDOW', self.withdraw)
|
||||
root.title('Pynche Details Window')
|
||||
root.iconname('Pynche Details Window')
|
||||
root.bind('<Alt-q>', self.__quit)
|
||||
root.bind('<Alt-Q>', self.__quit)
|
||||
root.bind('<Alt-w>', self.withdraw)
|
||||
root.bind('<Alt-W>', self.withdraw)
|
||||
# accelerators
|
||||
root.bind('<KeyPress-Left>', self.__minus1)
|
||||
root.bind('<KeyPress-Right>', self.__plus1)
|
||||
root.bind('<Control-KeyPress-Left>', self.__minus10)
|
||||
root.bind('<Control-KeyPress-Right>', self.__plus10)
|
||||
root.bind('<Shift-KeyPress-Left>', self.__minus25)
|
||||
root.bind('<Shift-KeyPress-Right>', self.__plus25)
|
||||
#
|
||||
# color ties
|
||||
frame = self.__frame = Frame(root)
|
||||
frame.pack(expand=YES, fill=X)
|
||||
self.__l1 = Label(frame, text='Move Sliders:')
|
||||
self.__l1.grid(row=1, column=0, sticky=E)
|
||||
self.__rvar = IntVar()
|
||||
self.__rvar.set(optiondb.get('RSLIDER', 4))
|
||||
self.__radio1 = Checkbutton(frame, text='Red',
|
||||
variable=self.__rvar,
|
||||
command=self.__effect,
|
||||
onvalue=4, offvalue=0)
|
||||
self.__radio1.grid(row=1, column=1, sticky=W)
|
||||
self.__gvar = IntVar()
|
||||
self.__gvar.set(optiondb.get('GSLIDER', 2))
|
||||
self.__radio2 = Checkbutton(frame, text='Green',
|
||||
variable=self.__gvar,
|
||||
command=self.__effect,
|
||||
onvalue=2, offvalue=0)
|
||||
self.__radio2.grid(row=2, column=1, sticky=W)
|
||||
self.__bvar = IntVar()
|
||||
self.__bvar.set(optiondb.get('BSLIDER', 1))
|
||||
self.__radio3 = Checkbutton(frame, text='Blue',
|
||||
variable=self.__bvar,
|
||||
command=self.__effect,
|
||||
onvalue=1, offvalue=0)
|
||||
self.__radio3.grid(row=3, column=1, sticky=W)
|
||||
self.__l2 = Label(frame)
|
||||
self.__l2.grid(row=4, column=1, sticky=W)
|
||||
self.__effect()
|
||||
#
|
||||
# Boundary behavior
|
||||
self.__l3 = Label(frame, text='At boundary:')
|
||||
self.__l3.grid(row=5, column=0, sticky=E)
|
||||
self.__boundvar = StringVar()
|
||||
self.__boundvar.set(optiondb.get('ATBOUND', STOP))
|
||||
self.__omenu = OptionMenu(frame, self.__boundvar,
|
||||
STOP, WRAP, RATIO, GRAV)
|
||||
self.__omenu.grid(row=5, column=1, sticky=W)
|
||||
self.__omenu.configure(width=17)
|
||||
#
|
||||
# Buttons
|
||||
frame = self.__btnframe = Frame(frame)
|
||||
frame.grid(row=0, column=0, columnspan=2, sticky='EW')
|
||||
self.__down25 = Button(frame, text='-25',
|
||||
command=self.__minus25)
|
||||
self.__down10 = Button(frame, text='-10',
|
||||
command=self.__minus10)
|
||||
self.__down1 = Button(frame, text='-1',
|
||||
command=self.__minus1)
|
||||
self.__up1 = Button(frame, text='+1',
|
||||
command=self.__plus1)
|
||||
self.__up10 = Button(frame, text='+10',
|
||||
command=self.__plus10)
|
||||
self.__up25 = Button(frame, text='+25',
|
||||
command=self.__plus25)
|
||||
self.__down25.pack(expand=YES, fill=X, side=LEFT)
|
||||
self.__down10.pack(expand=YES, fill=X, side=LEFT)
|
||||
self.__down1.pack(expand=YES, fill=X, side=LEFT)
|
||||
self.__up1.pack(expand=YES, fill=X, side=LEFT)
|
||||
self.__up10.pack(expand=YES, fill=X, side=LEFT)
|
||||
self.__up25.pack(expand=YES, fill=X, side=LEFT)
|
||||
|
||||
def __effect(self, event=None):
|
||||
tie = self.__rvar.get() + self.__gvar.get() + self.__bvar.get()
|
||||
if tie in (0, 1, 2, 4):
|
||||
text = ''
|
||||
else:
|
||||
text = '(= %s Level)' % {3: 'Cyan',
|
||||
5: 'Magenta',
|
||||
6: 'Yellow',
|
||||
7: 'Grey'}[tie]
|
||||
self.__l2.configure(text=text)
|
||||
|
||||
def __quit(self, event=None):
|
||||
self.__root.quit()
|
||||
|
||||
def withdraw(self, event=None):
|
||||
self.__root.withdraw()
|
||||
|
||||
def deiconify(self, event=None):
|
||||
self.__root.deiconify()
|
||||
|
||||
def __minus25(self, event=None):
|
||||
self.__delta(-25)
|
||||
|
||||
def __minus10(self, event=None):
|
||||
self.__delta(-10)
|
||||
|
||||
def __minus1(self, event=None):
|
||||
self.__delta(-1)
|
||||
|
||||
def __plus1(self, event=None):
|
||||
self.__delta(1)
|
||||
|
||||
def __plus10(self, event=None):
|
||||
self.__delta(10)
|
||||
|
||||
def __plus25(self, event=None):
|
||||
self.__delta(25)
|
||||
|
||||
def __delta(self, delta):
|
||||
tie = []
|
||||
if self.__rvar.get():
|
||||
red = self.__red + delta
|
||||
tie.append(red)
|
||||
else:
|
||||
red = self.__red
|
||||
if self.__gvar.get():
|
||||
green = self.__green + delta
|
||||
tie.append(green)
|
||||
else:
|
||||
green = self.__green
|
||||
if self.__bvar.get():
|
||||
blue = self.__blue + delta
|
||||
tie.append(blue)
|
||||
else:
|
||||
blue = self.__blue
|
||||
# now apply at boundary behavior
|
||||
atbound = self.__boundvar.get()
|
||||
if atbound == STOP:
|
||||
if red < 0 or green < 0 or blue < 0 or \
|
||||
red > 255 or green > 255 or blue > 255:
|
||||
# then
|
||||
red, green, blue = self.__red, self.__green, self.__blue
|
||||
elif atbound == WRAP or (atbound == RATIO and len(tie) < 2):
|
||||
if red < 0:
|
||||
red += 256
|
||||
if green < 0:
|
||||
green += 256
|
||||
if blue < 0:
|
||||
blue += 256
|
||||
if red > 255:
|
||||
red -= 256
|
||||
if green > 255:
|
||||
green -= 256
|
||||
if blue > 255:
|
||||
blue -= 256
|
||||
elif atbound == RATIO:
|
||||
# for when 2 or 3 colors are tied together
|
||||
dir = 0
|
||||
for c in tie:
|
||||
if c < 0:
|
||||
dir = -1
|
||||
elif c > 255:
|
||||
dir = 1
|
||||
if dir == -1:
|
||||
delta = max(tie)
|
||||
if self.__rvar.get():
|
||||
red = red + 255 - delta
|
||||
if self.__gvar.get():
|
||||
green = green + 255 - delta
|
||||
if self.__bvar.get():
|
||||
blue = blue + 255 - delta
|
||||
elif dir == 1:
|
||||
delta = min(tie)
|
||||
if self.__rvar.get():
|
||||
red = red - delta
|
||||
if self.__gvar.get():
|
||||
green = green - delta
|
||||
if self.__bvar.get():
|
||||
blue = blue - delta
|
||||
elif atbound == GRAV:
|
||||
if red < 0:
|
||||
red = 0
|
||||
if green < 0:
|
||||
green = 0
|
||||
if blue < 0:
|
||||
blue = 0
|
||||
if red > 255:
|
||||
red = 255
|
||||
if green > 255:
|
||||
green = 255
|
||||
if blue > 255:
|
||||
blue = 255
|
||||
self.__sb.update_views(red, green, blue)
|
||||
self.__root.update_idletasks()
|
||||
|
||||
def update_yourself(self, red, green, blue):
|
||||
self.__red = red
|
||||
self.__green = green
|
||||
self.__blue = blue
|
||||
|
||||
def save_options(self, optiondb):
|
||||
optiondb['RSLIDER'] = self.__rvar.get()
|
||||
optiondb['GSLIDER'] = self.__gvar.get()
|
||||
optiondb['BSLIDER'] = self.__bvar.get()
|
||||
optiondb['ATBOUND'] = self.__boundvar.get()
|
175
third_party/python/Tools/pynche/ListViewer.py
vendored
Normal file
175
third_party/python/Tools/pynche/ListViewer.py
vendored
Normal file
|
@ -0,0 +1,175 @@
|
|||
"""ListViewer class.
|
||||
|
||||
This class implements an input/output view on the color model. It lists every
|
||||
unique color (e.g. unique r/g/b value) found in the color database. Each
|
||||
color is shown by small swatch and primary color name. Some colors have
|
||||
aliases -- more than one name for the same r/g/b value. These aliases are
|
||||
displayed in the small listbox at the bottom of the screen.
|
||||
|
||||
Clicking on a color name or swatch selects that color and updates all other
|
||||
windows. When a color is selected in a different viewer, the color list is
|
||||
scrolled to the selected color and it is highlighted. If the selected color
|
||||
is an r/g/b value without a name, no scrolling occurs.
|
||||
|
||||
You can turn off Update On Click if all you want to see is the alias for a
|
||||
given name, without selecting the color.
|
||||
"""
|
||||
|
||||
from tkinter import *
|
||||
import ColorDB
|
||||
|
||||
ADDTOVIEW = 'Color %List Window...'
|
||||
|
||||
class ListViewer:
|
||||
def __init__(self, switchboard, master=None):
|
||||
self.__sb = switchboard
|
||||
optiondb = switchboard.optiondb()
|
||||
self.__lastbox = None
|
||||
self.__dontcenter = 0
|
||||
# GUI
|
||||
root = self.__root = Toplevel(master, class_='Pynche')
|
||||
root.protocol('WM_DELETE_WINDOW', self.withdraw)
|
||||
root.title('Pynche Color List')
|
||||
root.iconname('Pynche Color List')
|
||||
root.bind('<Alt-q>', self.__quit)
|
||||
root.bind('<Alt-Q>', self.__quit)
|
||||
root.bind('<Alt-w>', self.withdraw)
|
||||
root.bind('<Alt-W>', self.withdraw)
|
||||
#
|
||||
# create the canvas which holds everything, and its scrollbar
|
||||
#
|
||||
frame = self.__frame = Frame(root)
|
||||
frame.pack()
|
||||
canvas = self.__canvas = Canvas(frame, width=160, height=300,
|
||||
borderwidth=2, relief=SUNKEN)
|
||||
self.__scrollbar = Scrollbar(frame)
|
||||
self.__scrollbar.pack(fill=Y, side=RIGHT)
|
||||
canvas.pack(fill=BOTH, expand=1)
|
||||
canvas.configure(yscrollcommand=(self.__scrollbar, 'set'))
|
||||
self.__scrollbar.configure(command=(canvas, 'yview'))
|
||||
self.__populate()
|
||||
#
|
||||
# Update on click
|
||||
self.__uoc = BooleanVar()
|
||||
self.__uoc.set(optiondb.get('UPONCLICK', 1))
|
||||
self.__uocbtn = Checkbutton(root,
|
||||
text='Update on Click',
|
||||
variable=self.__uoc,
|
||||
command=self.__toggleupdate)
|
||||
self.__uocbtn.pack(expand=1, fill=BOTH)
|
||||
#
|
||||
# alias list
|
||||
self.__alabel = Label(root, text='Aliases:')
|
||||
self.__alabel.pack()
|
||||
self.__aliases = Listbox(root, height=5,
|
||||
selectmode=BROWSE)
|
||||
self.__aliases.pack(expand=1, fill=BOTH)
|
||||
|
||||
def __populate(self):
|
||||
#
|
||||
# create all the buttons
|
||||
colordb = self.__sb.colordb()
|
||||
canvas = self.__canvas
|
||||
row = 0
|
||||
widest = 0
|
||||
bboxes = self.__bboxes = []
|
||||
for name in colordb.unique_names():
|
||||
exactcolor = ColorDB.triplet_to_rrggbb(colordb.find_byname(name))
|
||||
canvas.create_rectangle(5, row*20 + 5,
|
||||
20, row*20 + 20,
|
||||
fill=exactcolor)
|
||||
textid = canvas.create_text(25, row*20 + 13,
|
||||
text=name,
|
||||
anchor=W)
|
||||
x1, y1, textend, y2 = canvas.bbox(textid)
|
||||
boxid = canvas.create_rectangle(3, row*20+3,
|
||||
textend+3, row*20 + 23,
|
||||
outline='',
|
||||
tags=(exactcolor, 'all'))
|
||||
canvas.bind('<ButtonRelease>', self.__onrelease)
|
||||
bboxes.append(boxid)
|
||||
if textend+3 > widest:
|
||||
widest = textend+3
|
||||
row += 1
|
||||
canvheight = (row-1)*20 + 25
|
||||
canvas.config(scrollregion=(0, 0, 150, canvheight))
|
||||
for box in bboxes:
|
||||
x1, y1, x2, y2 = canvas.coords(box)
|
||||
canvas.coords(box, x1, y1, widest, y2)
|
||||
|
||||
def __onrelease(self, event=None):
|
||||
canvas = self.__canvas
|
||||
# find the current box
|
||||
x = canvas.canvasx(event.x)
|
||||
y = canvas.canvasy(event.y)
|
||||
ids = canvas.find_overlapping(x, y, x, y)
|
||||
for boxid in ids:
|
||||
if boxid in self.__bboxes:
|
||||
break
|
||||
else:
|
||||
## print 'No box found!'
|
||||
return
|
||||
tags = self.__canvas.gettags(boxid)
|
||||
for t in tags:
|
||||
if t[0] == '#':
|
||||
break
|
||||
else:
|
||||
## print 'No color tag found!'
|
||||
return
|
||||
red, green, blue = ColorDB.rrggbb_to_triplet(t)
|
||||
self.__dontcenter = 1
|
||||
if self.__uoc.get():
|
||||
self.__sb.update_views(red, green, blue)
|
||||
else:
|
||||
self.update_yourself(red, green, blue)
|
||||
self.__red, self.__green, self.__blue = red, green, blue
|
||||
|
||||
def __toggleupdate(self, event=None):
|
||||
if self.__uoc.get():
|
||||
self.__sb.update_views(self.__red, self.__green, self.__blue)
|
||||
|
||||
def __quit(self, event=None):
|
||||
self.__root.quit()
|
||||
|
||||
def withdraw(self, event=None):
|
||||
self.__root.withdraw()
|
||||
|
||||
def deiconify(self, event=None):
|
||||
self.__root.deiconify()
|
||||
|
||||
def update_yourself(self, red, green, blue):
|
||||
canvas = self.__canvas
|
||||
# turn off the last box
|
||||
if self.__lastbox:
|
||||
canvas.itemconfigure(self.__lastbox, outline='')
|
||||
# turn on the current box
|
||||
colortag = ColorDB.triplet_to_rrggbb((red, green, blue))
|
||||
canvas.itemconfigure(colortag, outline='black')
|
||||
self.__lastbox = colortag
|
||||
# fill the aliases
|
||||
self.__aliases.delete(0, END)
|
||||
try:
|
||||
aliases = self.__sb.colordb().aliases_of(red, green, blue)[1:]
|
||||
except ColorDB.BadColor:
|
||||
self.__aliases.insert(END, '<no matching color>')
|
||||
return
|
||||
if not aliases:
|
||||
self.__aliases.insert(END, '<no aliases>')
|
||||
else:
|
||||
for name in aliases:
|
||||
self.__aliases.insert(END, name)
|
||||
# maybe scroll the canvas so that the item is visible
|
||||
if self.__dontcenter:
|
||||
self.__dontcenter = 0
|
||||
else:
|
||||
ig, ig, ig, y1 = canvas.coords(colortag)
|
||||
ig, ig, ig, y2 = canvas.coords(self.__bboxes[-1])
|
||||
h = int(canvas['height']) * 0.5
|
||||
canvas.yview('moveto', (y1-h) / y2)
|
||||
|
||||
def save_options(self, optiondb):
|
||||
optiondb['UPONCLICK'] = self.__uoc.get()
|
||||
|
||||
def colordb_changed(self, colordb):
|
||||
self.__canvas.delete('all')
|
||||
self.__populate()
|
229
third_party/python/Tools/pynche/Main.py
vendored
Normal file
229
third_party/python/Tools/pynche/Main.py
vendored
Normal file
|
@ -0,0 +1,229 @@
|
|||
"""Pynche -- The PYthon Natural Color and Hue Editor.
|
||||
|
||||
Contact: %(AUTHNAME)s
|
||||
Email: %(AUTHEMAIL)s
|
||||
Version: %(__version__)s
|
||||
|
||||
Pynche is based largely on a similar color editor I wrote years ago for the
|
||||
SunView window system. That editor was called ICE: the Interactive Color
|
||||
Editor. I'd always wanted to port the editor to X but didn't feel like
|
||||
hacking X and C code to do it. Fast forward many years, to where Python +
|
||||
Tkinter provides such a nice programming environment, with enough power, that
|
||||
I finally buckled down and implemented it. I changed the name because these
|
||||
days, too many other systems have the acronym `ICE'.
|
||||
|
||||
This program currently requires Python 2.2 with Tkinter.
|
||||
|
||||
Usage: %(PROGRAM)s [-d file] [-i file] [-X] [-v] [-h] [initialcolor]
|
||||
|
||||
Where:
|
||||
--database file
|
||||
-d file
|
||||
Alternate location of a color database file
|
||||
|
||||
--initfile file
|
||||
-i file
|
||||
Alternate location of the initialization file. This file contains a
|
||||
persistent database of the current Pynche options and color. This
|
||||
means that Pynche restores its option settings and current color when
|
||||
it restarts, using this file (unless the -X option is used). The
|
||||
default is ~/.pynche
|
||||
|
||||
--ignore
|
||||
-X
|
||||
Ignore the initialization file when starting up. Pynche will still
|
||||
write the current option settings to this file when it quits.
|
||||
|
||||
--version
|
||||
-v
|
||||
print the version number and exit
|
||||
|
||||
--help
|
||||
-h
|
||||
print this message
|
||||
|
||||
initialcolor
|
||||
initial color, as a color name or #RRGGBB format
|
||||
"""
|
||||
|
||||
__version__ = '1.4.1'
|
||||
|
||||
import sys
|
||||
import os
|
||||
import getopt
|
||||
import ColorDB
|
||||
|
||||
from PyncheWidget import PyncheWidget
|
||||
from Switchboard import Switchboard
|
||||
from StripViewer import StripViewer
|
||||
from ChipViewer import ChipViewer
|
||||
from TypeinViewer import TypeinViewer
|
||||
|
||||
|
||||
|
||||
PROGRAM = sys.argv[0]
|
||||
AUTHNAME = 'Barry Warsaw'
|
||||
AUTHEMAIL = 'barry@python.org'
|
||||
|
||||
# Default locations of rgb.txt or other textual color database
|
||||
RGB_TXT = [
|
||||
# Solaris OpenWindows
|
||||
'/usr/openwin/lib/rgb.txt',
|
||||
# Linux
|
||||
'/usr/lib/X11/rgb.txt',
|
||||
# The X11R6.4 rgb.txt file
|
||||
os.path.join(sys.path[0], 'X/rgb.txt'),
|
||||
# add more here
|
||||
]
|
||||
|
||||
|
||||
|
||||
# Do this because PyncheWidget.py wants to get at the interpolated docstring
|
||||
# too, for its Help menu.
|
||||
def docstring():
|
||||
return __doc__ % globals()
|
||||
|
||||
|
||||
def usage(code, msg=''):
|
||||
print(docstring())
|
||||
if msg:
|
||||
print(msg)
|
||||
sys.exit(code)
|
||||
|
||||
|
||||
|
||||
def initial_color(s, colordb):
|
||||
# function called on every color
|
||||
def scan_color(s, colordb=colordb):
|
||||
try:
|
||||
r, g, b = colordb.find_byname(s)
|
||||
except ColorDB.BadColor:
|
||||
try:
|
||||
r, g, b = ColorDB.rrggbb_to_triplet(s)
|
||||
except ColorDB.BadColor:
|
||||
return None, None, None
|
||||
return r, g, b
|
||||
#
|
||||
# First try the passed in color
|
||||
r, g, b = scan_color(s)
|
||||
if r is None:
|
||||
# try the same color with '#' prepended, since some shells require
|
||||
# this to be escaped, which is a pain
|
||||
r, g, b = scan_color('#' + s)
|
||||
if r is None:
|
||||
print('Bad initial color, using gray50:', s)
|
||||
r, g, b = scan_color('gray50')
|
||||
if r is None:
|
||||
usage(1, 'Cannot find an initial color to use')
|
||||
# does not return
|
||||
return r, g, b
|
||||
|
||||
|
||||
|
||||
def build(master=None, initialcolor=None, initfile=None, ignore=None,
|
||||
dbfile=None):
|
||||
# create all output widgets
|
||||
s = Switchboard(not ignore and initfile)
|
||||
# defer to the command line chosen color database, falling back to the one
|
||||
# in the .pynche file.
|
||||
if dbfile is None:
|
||||
dbfile = s.optiondb().get('DBFILE')
|
||||
# find a parseable color database
|
||||
colordb = None
|
||||
files = RGB_TXT[:]
|
||||
if dbfile is None:
|
||||
dbfile = files.pop()
|
||||
while colordb is None:
|
||||
try:
|
||||
colordb = ColorDB.get_colordb(dbfile)
|
||||
except (KeyError, IOError):
|
||||
pass
|
||||
if colordb is None:
|
||||
if not files:
|
||||
break
|
||||
dbfile = files.pop(0)
|
||||
if not colordb:
|
||||
usage(1, 'No color database file found, see the -d option.')
|
||||
s.set_colordb(colordb)
|
||||
|
||||
# create the application window decorations
|
||||
app = PyncheWidget(__version__, s, master=master)
|
||||
w = app.window()
|
||||
|
||||
# these built-in viewers live inside the main Pynche window
|
||||
s.add_view(StripViewer(s, w))
|
||||
s.add_view(ChipViewer(s, w))
|
||||
s.add_view(TypeinViewer(s, w))
|
||||
|
||||
# get the initial color as components and set the color on all views. if
|
||||
# there was no initial color given on the command line, use the one that's
|
||||
# stored in the option database
|
||||
if initialcolor is None:
|
||||
optiondb = s.optiondb()
|
||||
red = optiondb.get('RED')
|
||||
green = optiondb.get('GREEN')
|
||||
blue = optiondb.get('BLUE')
|
||||
# but if there wasn't any stored in the database, use grey50
|
||||
if red is None or blue is None or green is None:
|
||||
red, green, blue = initial_color('grey50', colordb)
|
||||
else:
|
||||
red, green, blue = initial_color(initialcolor, colordb)
|
||||
s.update_views(red, green, blue)
|
||||
return app, s
|
||||
|
||||
|
||||
def run(app, s):
|
||||
try:
|
||||
app.start()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
opts, args = getopt.getopt(
|
||||
sys.argv[1:],
|
||||
'hd:i:Xv',
|
||||
['database=', 'initfile=', 'ignore', 'help', 'version'])
|
||||
except getopt.error as msg:
|
||||
usage(1, msg)
|
||||
|
||||
if len(args) == 0:
|
||||
initialcolor = None
|
||||
elif len(args) == 1:
|
||||
initialcolor = args[0]
|
||||
else:
|
||||
usage(1)
|
||||
|
||||
ignore = False
|
||||
dbfile = None
|
||||
initfile = os.path.expanduser('~/.pynche')
|
||||
for opt, arg in opts:
|
||||
if opt in ('-h', '--help'):
|
||||
usage(0)
|
||||
elif opt in ('-v', '--version'):
|
||||
print("""\
|
||||
Pynche -- The PYthon Natural Color and Hue Editor.
|
||||
Contact: %(AUTHNAME)s
|
||||
Email: %(AUTHEMAIL)s
|
||||
Version: %(__version__)s""" % globals())
|
||||
sys.exit(0)
|
||||
elif opt in ('-d', '--database'):
|
||||
dbfile = arg
|
||||
elif opt in ('-X', '--ignore'):
|
||||
ignore = True
|
||||
elif opt in ('-i', '--initfile'):
|
||||
initfile = arg
|
||||
|
||||
app, sb = build(initialcolor=initialcolor,
|
||||
initfile=initfile,
|
||||
ignore=ignore,
|
||||
dbfile=dbfile)
|
||||
run(app, sb)
|
||||
sb.save_views()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
313
third_party/python/Tools/pynche/PyncheWidget.py
vendored
Normal file
313
third_party/python/Tools/pynche/PyncheWidget.py
vendored
Normal file
|
@ -0,0 +1,313 @@
|
|||
"""Main Pynche (Pythonically Natural Color and Hue Editor) widget.
|
||||
|
||||
This window provides the basic decorations, primarily including the menubar.
|
||||
It is used to bring up other windows.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from tkinter import *
|
||||
from tkinter import messagebox, filedialog
|
||||
import ColorDB
|
||||
|
||||
# Milliseconds between interrupt checks
|
||||
KEEPALIVE_TIMER = 500
|
||||
|
||||
|
||||
|
||||
class PyncheWidget:
|
||||
def __init__(self, version, switchboard, master=None, extrapath=[]):
|
||||
self.__sb = switchboard
|
||||
self.__version = version
|
||||
self.__textwin = None
|
||||
self.__listwin = None
|
||||
self.__detailswin = None
|
||||
self.__helpwin = None
|
||||
self.__dialogstate = {}
|
||||
modal = self.__modal = not not master
|
||||
# If a master was given, we are running as a modal dialog servant to
|
||||
# some other application. We rearrange our UI in this case (there's
|
||||
# no File menu and we get `Okay' and `Cancel' buttons), and we do a
|
||||
# grab_set() to make ourselves modal
|
||||
if modal:
|
||||
self.__tkroot = tkroot = Toplevel(master, class_='Pynche')
|
||||
tkroot.grab_set()
|
||||
tkroot.withdraw()
|
||||
else:
|
||||
# Is there already a default root for Tk, say because we're
|
||||
# running under Guido's IDE? :-) Two conditions say no, either the
|
||||
# import fails or _default_root is None.
|
||||
tkroot = None
|
||||
try:
|
||||
from Tkinter import _default_root
|
||||
tkroot = self.__tkroot = _default_root
|
||||
except ImportError:
|
||||
pass
|
||||
if not tkroot:
|
||||
tkroot = self.__tkroot = Tk(className='Pynche')
|
||||
# but this isn't our top level widget, so make it invisible
|
||||
tkroot.withdraw()
|
||||
# create the menubar
|
||||
menubar = self.__menubar = Menu(tkroot)
|
||||
#
|
||||
# File menu
|
||||
#
|
||||
filemenu = self.__filemenu = Menu(menubar, tearoff=0)
|
||||
filemenu.add_command(label='Load palette...',
|
||||
command=self.__load,
|
||||
underline=0)
|
||||
if not modal:
|
||||
filemenu.add_command(label='Quit',
|
||||
command=self.__quit,
|
||||
accelerator='Alt-Q',
|
||||
underline=0)
|
||||
#
|
||||
# View menu
|
||||
#
|
||||
views = make_view_popups(self.__sb, self.__tkroot, extrapath)
|
||||
viewmenu = Menu(menubar, tearoff=0)
|
||||
for v in views:
|
||||
viewmenu.add_command(label=v.menutext(),
|
||||
command=v.popup,
|
||||
underline=v.underline())
|
||||
#
|
||||
# Help menu
|
||||
#
|
||||
helpmenu = Menu(menubar, name='help', tearoff=0)
|
||||
helpmenu.add_command(label='About Pynche...',
|
||||
command=self.__popup_about,
|
||||
underline=0)
|
||||
helpmenu.add_command(label='Help...',
|
||||
command=self.__popup_usage,
|
||||
underline=0)
|
||||
#
|
||||
# Tie them all together
|
||||
#
|
||||
menubar.add_cascade(label='File',
|
||||
menu=filemenu,
|
||||
underline=0)
|
||||
menubar.add_cascade(label='View',
|
||||
menu=viewmenu,
|
||||
underline=0)
|
||||
menubar.add_cascade(label='Help',
|
||||
menu=helpmenu,
|
||||
underline=0)
|
||||
|
||||
# now create the top level window
|
||||
root = self.__root = Toplevel(tkroot, class_='Pynche', menu=menubar)
|
||||
root.protocol('WM_DELETE_WINDOW',
|
||||
modal and self.__bell or self.__quit)
|
||||
root.title('Pynche %s' % version)
|
||||
root.iconname('Pynche')
|
||||
# Only bind accelerators for the File->Quit menu item if running as a
|
||||
# standalone app
|
||||
if not modal:
|
||||
root.bind('<Alt-q>', self.__quit)
|
||||
root.bind('<Alt-Q>', self.__quit)
|
||||
else:
|
||||
# We're a modal dialog so we have a new row of buttons
|
||||
bframe = Frame(root, borderwidth=1, relief=RAISED)
|
||||
bframe.grid(row=4, column=0, columnspan=2,
|
||||
sticky='EW',
|
||||
ipady=5)
|
||||
okay = Button(bframe,
|
||||
text='Okay',
|
||||
command=self.__okay)
|
||||
okay.pack(side=LEFT, expand=1)
|
||||
cancel = Button(bframe,
|
||||
text='Cancel',
|
||||
command=self.__cancel)
|
||||
cancel.pack(side=LEFT, expand=1)
|
||||
|
||||
def __quit(self, event=None):
|
||||
self.__tkroot.quit()
|
||||
|
||||
def __bell(self, event=None):
|
||||
self.__tkroot.bell()
|
||||
|
||||
def __okay(self, event=None):
|
||||
self.__sb.withdraw_views()
|
||||
self.__tkroot.grab_release()
|
||||
self.__quit()
|
||||
|
||||
def __cancel(self, event=None):
|
||||
self.__sb.canceled()
|
||||
self.__okay()
|
||||
|
||||
def __keepalive(self):
|
||||
# Exercise the Python interpreter regularly so keyboard interrupts get
|
||||
# through.
|
||||
self.__tkroot.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive)
|
||||
|
||||
def start(self):
|
||||
if not self.__modal:
|
||||
self.__keepalive()
|
||||
self.__tkroot.mainloop()
|
||||
|
||||
def window(self):
|
||||
return self.__root
|
||||
|
||||
def __popup_about(self, event=None):
|
||||
from Main import __version__
|
||||
messagebox.showinfo('About Pynche ' + __version__,
|
||||
'''\
|
||||
Pynche %s
|
||||
The PYthonically Natural
|
||||
Color and Hue Editor
|
||||
|
||||
For information
|
||||
contact: Barry A. Warsaw
|
||||
email: bwarsaw@python.org''' % __version__)
|
||||
|
||||
def __popup_usage(self, event=None):
|
||||
if not self.__helpwin:
|
||||
self.__helpwin = Helpwin(self.__root, self.__quit)
|
||||
self.__helpwin.deiconify()
|
||||
|
||||
def __load(self, event=None):
|
||||
while 1:
|
||||
idir, ifile = os.path.split(self.__sb.colordb().filename())
|
||||
file = filedialog.askopenfilename(
|
||||
filetypes=[('Text files', '*.txt'),
|
||||
('All files', '*'),
|
||||
],
|
||||
initialdir=idir,
|
||||
initialfile=ifile)
|
||||
if not file:
|
||||
# cancel button
|
||||
return
|
||||
try:
|
||||
colordb = ColorDB.get_colordb(file)
|
||||
except IOError:
|
||||
messagebox.showerror('Read error', '''\
|
||||
Could not open file for reading:
|
||||
%s''' % file)
|
||||
continue
|
||||
if colordb is None:
|
||||
messagebox.showerror('Unrecognized color file type', '''\
|
||||
Unrecognized color file type in file:
|
||||
%s''' % file)
|
||||
continue
|
||||
break
|
||||
self.__sb.set_colordb(colordb)
|
||||
|
||||
def withdraw(self):
|
||||
self.__root.withdraw()
|
||||
|
||||
def deiconify(self):
|
||||
self.__root.deiconify()
|
||||
|
||||
|
||||
|
||||
class Helpwin:
|
||||
def __init__(self, master, quitfunc):
|
||||
from Main import docstring
|
||||
self.__root = root = Toplevel(master, class_='Pynche')
|
||||
root.protocol('WM_DELETE_WINDOW', self.__withdraw)
|
||||
root.title('Pynche Help Window')
|
||||
root.iconname('Pynche Help Window')
|
||||
root.bind('<Alt-q>', quitfunc)
|
||||
root.bind('<Alt-Q>', quitfunc)
|
||||
root.bind('<Alt-w>', self.__withdraw)
|
||||
root.bind('<Alt-W>', self.__withdraw)
|
||||
|
||||
# more elaborate help is available in the README file
|
||||
readmefile = os.path.join(sys.path[0], 'README')
|
||||
try:
|
||||
fp = None
|
||||
try:
|
||||
fp = open(readmefile)
|
||||
contents = fp.read()
|
||||
# wax the last page, it contains Emacs cruft
|
||||
i = contents.rfind('\f')
|
||||
if i > 0:
|
||||
contents = contents[:i].rstrip()
|
||||
finally:
|
||||
if fp:
|
||||
fp.close()
|
||||
except IOError:
|
||||
sys.stderr.write("Couldn't open Pynche's README, "
|
||||
'using docstring instead.\n')
|
||||
contents = docstring()
|
||||
|
||||
self.__text = text = Text(root, relief=SUNKEN,
|
||||
width=80, height=24)
|
||||
self.__text.focus_set()
|
||||
text.insert(0.0, contents)
|
||||
scrollbar = Scrollbar(root)
|
||||
scrollbar.pack(fill=Y, side=RIGHT)
|
||||
text.pack(fill=BOTH, expand=YES)
|
||||
text.configure(yscrollcommand=(scrollbar, 'set'))
|
||||
scrollbar.configure(command=(text, 'yview'))
|
||||
|
||||
def __withdraw(self, event=None):
|
||||
self.__root.withdraw()
|
||||
|
||||
def deiconify(self):
|
||||
self.__root.deiconify()
|
||||
|
||||
|
||||
|
||||
import functools
|
||||
@functools.total_ordering
|
||||
class PopupViewer:
|
||||
def __init__(self, module, name, switchboard, root):
|
||||
self.__m = module
|
||||
self.__name = name
|
||||
self.__sb = switchboard
|
||||
self.__root = root
|
||||
self.__menutext = module.ADDTOVIEW
|
||||
# find the underline character
|
||||
underline = module.ADDTOVIEW.find('%')
|
||||
if underline == -1:
|
||||
underline = 0
|
||||
else:
|
||||
self.__menutext = module.ADDTOVIEW.replace('%', '', 1)
|
||||
self.__underline = underline
|
||||
self.__window = None
|
||||
|
||||
def menutext(self):
|
||||
return self.__menutext
|
||||
|
||||
def underline(self):
|
||||
return self.__underline
|
||||
|
||||
def popup(self, event=None):
|
||||
if not self.__window:
|
||||
# class and module must have the same name
|
||||
class_ = getattr(self.__m, self.__name)
|
||||
self.__window = class_(self.__sb, self.__root)
|
||||
self.__sb.add_view(self.__window)
|
||||
self.__window.deiconify()
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.__menutext == other.__menutext
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.__menutext < other.__menutext
|
||||
|
||||
|
||||
def make_view_popups(switchboard, root, extrapath):
|
||||
viewers = []
|
||||
# where we are in the file system
|
||||
dirs = [os.path.dirname(__file__)] + extrapath
|
||||
for dir in dirs:
|
||||
if dir == '':
|
||||
dir = '.'
|
||||
for file in os.listdir(dir):
|
||||
if file[-9:] == 'Viewer.py':
|
||||
name = file[:-3]
|
||||
try:
|
||||
module = __import__(name)
|
||||
except ImportError:
|
||||
# Pynche is running from inside a package, so get the
|
||||
# module using the explicit path.
|
||||
pkg = __import__('pynche.'+name)
|
||||
module = getattr(pkg, name)
|
||||
if hasattr(module, 'ADDTOVIEW') and module.ADDTOVIEW:
|
||||
# this is an external viewer
|
||||
v = PopupViewer(module, name, switchboard, root)
|
||||
viewers.append(v)
|
||||
# sort alphabetically
|
||||
viewers.sort()
|
||||
return viewers
|
398
third_party/python/Tools/pynche/README
vendored
Normal file
398
third_party/python/Tools/pynche/README
vendored
Normal file
|
@ -0,0 +1,398 @@
|
|||
Pynche - The PYthonically Natural Color and Hue Editor
|
||||
|
||||
Contact: Barry A. Warsaw
|
||||
Email: bwarsaw@python.org
|
||||
Version: 1.3
|
||||
|
||||
Introduction
|
||||
|
||||
Pynche is a color editor based largely on a similar program that I
|
||||
originally wrote back in 1987 for the Sunview window system. That
|
||||
editor was called ICE, the Interactive Color Editor. I'd always
|
||||
wanted to port this program to X but didn't feel like hacking X
|
||||
and C code to do it. Fast forward many years, to where Python +
|
||||
Tkinter provides such a nice programming environment, with enough
|
||||
power, that I finally buckled down and re-implemented it. I
|
||||
changed the name because these days, too many other systems have
|
||||
the acronym `ICE'.
|
||||
|
||||
Pynche should work with any variant of Python after 1.5.2
|
||||
(e.g. 2.0.1 and 2.1.1), using Tk 8.0.x. It's been tested on
|
||||
Solaris 2.6, Windows NT 4, and various Linux distros. You'll want
|
||||
to be sure to have at least Tk 8.0.3 for Windows. Also, Pynche is
|
||||
very colormap intensive, so it doesn't work very well on 8-bit
|
||||
graphics cards; 24bit+ graphics cards are so cheap these days,
|
||||
I'll probably never "fix" that.
|
||||
|
||||
Pynche must find a text database of colors names in order to
|
||||
provide `nearest' color matching. Pynche is distributed with an
|
||||
rgb.txt file from the X11R6.4 distribution for this reason, along
|
||||
with other "Web related" database (see below). You can use a
|
||||
different file with the -d option. The file xlicense.txt contains
|
||||
the license only for rgb.txt and both files are in the X/
|
||||
subdirectory.
|
||||
|
||||
Pynche is pronounced: Pin'-chee
|
||||
|
||||
|
||||
Running Standalone
|
||||
|
||||
On Unix, start it by running the `pynche' script. On Windows, run
|
||||
pynche.pyw to inhibit the console window. When run from the
|
||||
command line, the following options are recognized:
|
||||
|
||||
--database file
|
||||
-d file
|
||||
Alternate location of the color database file. Without this
|
||||
option, the first valid file found will be used (see below).
|
||||
|
||||
--initfile file
|
||||
-i file
|
||||
Alternate location of the persistent initialization file. See
|
||||
the section on Persistency below.
|
||||
|
||||
--ignore
|
||||
-X
|
||||
Ignore the persistent initialization file when starting up.
|
||||
Pynche will still write the current option settings to the
|
||||
persistent init file when it quits.
|
||||
|
||||
--help
|
||||
-h
|
||||
Print the help message.
|
||||
|
||||
initialcolor
|
||||
a Tk color name or #rrggbb color spec to be used as the
|
||||
initially selected color. This overrides any color saved in
|
||||
the persistent init file. Since `#' needs to be escaped in
|
||||
many shells, it is optional in the spec (e.g. #45dd1f is the
|
||||
same as 45dd1f).
|
||||
|
||||
|
||||
Running as a Modal Dialog
|
||||
|
||||
Pynche can be run as a modal dialog, inside another application,
|
||||
say as a general color chooser. In fact, Grail 0.6 uses Pynche
|
||||
and a future version of IDLE may as well. Pynche supports the API
|
||||
implemented by the Tkinter standard tkColorChooser module, with a
|
||||
few changes as described below. By importing pyColorChooser from
|
||||
the Pynche package, you can run
|
||||
|
||||
pyColorChooser.askcolor()
|
||||
|
||||
which will popup Pynche as a modal dialog, and return the selected
|
||||
color.
|
||||
|
||||
There are some UI differences when running as a modal
|
||||
vs. standalone. When running as a modal, there is no "Quit" menu
|
||||
item under the "File" menu. Instead there are "Okay" and "Cancel"
|
||||
buttons.
|
||||
|
||||
When "Okay" is hit, askcolor() returns the tuple
|
||||
|
||||
((r, g, b), "name")
|
||||
|
||||
where r, g, and b are red, green, and blue color values
|
||||
respectively (in the range 0 to 255). "name" will be a color name
|
||||
from the color database if there is an exact match, otherwise it
|
||||
will be an X11 color spec of the form "#rrggbb". Note that this
|
||||
is different than tkColorChooser, which doesn't know anything
|
||||
about color names.
|
||||
|
||||
askcolor() supports the following optional keyword arguments:
|
||||
|
||||
color
|
||||
the color to set as the initial selected color
|
||||
|
||||
master[*]
|
||||
the master window to use as the parent of the modal
|
||||
dialog. Without this argument, pyColorChooser will create
|
||||
its own Tkinter.Tk instance as the master. This may not
|
||||
be what you want.
|
||||
|
||||
databasefile
|
||||
similar to the --database option, the value must be a
|
||||
file name
|
||||
|
||||
initfile[*]
|
||||
similar to the --initfile option, the value must be a
|
||||
file name
|
||||
|
||||
ignore[*]
|
||||
similar to the --ignore flag, the value is a boolean
|
||||
|
||||
wantspec
|
||||
When this is true, the "name" field in the return tuple
|
||||
will always be a color spec of the form "#rrggbb". It
|
||||
will not return a color name even if there is a match;
|
||||
this is so pyColorChooser can exactly match the API of
|
||||
tkColorChooser.
|
||||
|
||||
[*] these arguments must be specified the first time
|
||||
askcolor() is used and cannot be changed on subsequent calls.
|
||||
|
||||
|
||||
The Colorstrip Window
|
||||
|
||||
The top part of the main Pynche window contains the "variation
|
||||
strips". Each strip contains a number of "color chips". The
|
||||
strips always indicate the currently selected color by a highlight
|
||||
rectangle around the selected color chip, with an arrow pointing
|
||||
to the chip. Each arrow has an associated number giving you the
|
||||
color value along the variation's axis. Each variation strip
|
||||
shows you the colors that are reachable from the selected color by
|
||||
varying just one axis of the color solid.
|
||||
|
||||
For example, when the selected color is (in Red/Green/Blue
|
||||
notation) 127/127/127, the Red Variations strip shows you every
|
||||
color in the range 0/127/127 to 255/127/127. Similarly for the
|
||||
green and blue axes. You can select any color by clicking on its
|
||||
chip. This will update the highlight rectangle and the arrow, as
|
||||
well as other displays in Pynche.
|
||||
|
||||
Click on "Update while dragging" if you want Pynche to update the
|
||||
selected color while you drag along any variation strip (this will
|
||||
be a bit slower). Click on "Hexadecimal" to display the arrow
|
||||
numbers in hex.
|
||||
|
||||
There are also two shortcut buttons in this window, which
|
||||
auto-select Black (0/0/0) and White (255/255/255).
|
||||
|
||||
|
||||
The Proof Window
|
||||
|
||||
In the lower left corner of the main window you see two larger
|
||||
color chips. The Selected chip shows you a larger version of the
|
||||
color selected in the variation strips, along with its X11 color
|
||||
specification. The Nearest chip shows you the closest color in
|
||||
the X11 database to the selected color, giving its X11 color
|
||||
specification, and below that, its X11 color name. When the
|
||||
Selected chip color exactly matches the Nearest chip color, you
|
||||
will see the color name appear below the color specification for
|
||||
the Selected chip.
|
||||
|
||||
Clicking on the Nearest color chip selects that color. Color
|
||||
distance is calculated in the 3D space of the RGB color solid and
|
||||
if more than one color name is the same distance from the selected
|
||||
color, the first one found will be chosen.
|
||||
|
||||
Note that there may be more than one X11 color name for the same
|
||||
RGB value. In that case, the first one found in the text database
|
||||
is designated the "primary" name, and this is shown under the
|
||||
Nearest chip. The other names are "aliases" and they are visible
|
||||
in the Color List Window (see below).
|
||||
|
||||
Both the color specifications and color names are selectable for
|
||||
copying and pasting into another window.
|
||||
|
||||
|
||||
The Type-in Window
|
||||
|
||||
At the lower right of the main window are three entry fields.
|
||||
Here you can type numeric values for any of the three color axes.
|
||||
Legal values are between 0 and 255, and these fields do not allow
|
||||
you to enter illegal values. You must hit Enter or Tab to select
|
||||
the new color.
|
||||
|
||||
Click on "Update while typing" if you want Pynche to select the
|
||||
color on every keystroke (well, every one that produces a legal
|
||||
value!) Click on "Hexadecimal" to display and enter color values
|
||||
in hex.
|
||||
|
||||
|
||||
Other Views
|
||||
|
||||
There are three secondary windows which are not displayed by
|
||||
default. You can bring these up via the "View" menu on the main
|
||||
Pynche window.
|
||||
|
||||
|
||||
The Text Window
|
||||
|
||||
The "Text Window" allows you to see what effects various colors
|
||||
have on the standard Tk text widget elements. In the upper part
|
||||
of the window is a plain Tk text widget and here you can edit the
|
||||
text, select a region of text, etc. Below this is a button "Track
|
||||
color changes". When this is turned on, any colors selected in
|
||||
the other windows will change the text widget element specified in
|
||||
the radio buttons below. When this is turned off, text widget
|
||||
elements are not affected by color selection.
|
||||
|
||||
You can choose which element gets changed by color selection by
|
||||
clicking on one of the radio buttons in the bottom part of this
|
||||
window. Text foreground and background affect the text in the
|
||||
upper part of the window. Selection foreground and background
|
||||
affect the colors of the primary selection which is what you see
|
||||
when you click the middle button (depending on window system) and
|
||||
drag it through some text.
|
||||
|
||||
The Insertion is the insertion cursor in the text window, where
|
||||
new text will be inserted as you type. The insertion cursor only
|
||||
has a background.
|
||||
|
||||
|
||||
The Color List Window
|
||||
|
||||
The "Color List" window shows every named color in the color name
|
||||
database (this window may take a while to come up). In the upper
|
||||
part of the window you see a scrolling list of all the color names
|
||||
in the database, in alphabetical order. Click on any color to
|
||||
select it. In the bottom part of the window is displayed any
|
||||
aliases for the selected color (those color names that have the
|
||||
same RGB value, but were found later in the text database). For
|
||||
example, find the color "Black" and you'll see that its aliases
|
||||
are "gray0" and "grey0".
|
||||
|
||||
If the color has no aliases you'll see "<no aliases>" here. If you
|
||||
just want to see if a color has an alias, and do not want to select a
|
||||
color when you click on it, turn off "Update on Click".
|
||||
|
||||
Note that the color list is always updated when a color is selected
|
||||
from the main window. There's no way to turn this feature off. If
|
||||
the selected color has no matching color name you'll see
|
||||
"<no matching color>" in the Aliases window.
|
||||
|
||||
|
||||
The Details Window
|
||||
|
||||
The "Details" window gives you more control over color selection
|
||||
than just clicking on a color chip in the main window. The row of
|
||||
buttons along the top apply the specified increment and decrement
|
||||
amounts to the selected color. These delta amounts are applied to
|
||||
the variation strips specified by the check boxes labeled "Move
|
||||
Sliders". Thus if just Red and Green are selected, hitting -10
|
||||
will subtract 10 from the color value along the red and green
|
||||
variation only. Note the message under the checkboxes; this
|
||||
indicates the primary color level being changed when more than one
|
||||
slider is tied together. For example, if Red and Green are
|
||||
selected, you will be changing the Yellow level of the selected
|
||||
color.
|
||||
|
||||
The "At Boundary" behavior determines what happens when any color
|
||||
variation hits either the lower or upper boundaries (0 or 255) as
|
||||
a result of clicking on the top row buttons:
|
||||
|
||||
Stop
|
||||
When the increment or decrement would send any of the tied
|
||||
variations out of bounds, the entire delta is discarded.
|
||||
|
||||
Wrap Around
|
||||
When the increment or decrement would send any of the tied
|
||||
variations out of bounds, the out of bounds value is wrapped
|
||||
around to the other side. Thus if red were at 238 and +25
|
||||
were clicked, red would have the value 7.
|
||||
|
||||
Preserve Distance
|
||||
When the increment or decrement would send any of the tied
|
||||
variations out of bounds, all tied variations are wrapped as
|
||||
one, so as to preserve the distance between them. Thus if
|
||||
green and blue were tied, and green was at 238 while blue was
|
||||
at 223, and +25 were clicked, green would be at 15 and blue
|
||||
would be at 0.
|
||||
|
||||
Squash
|
||||
When the increment or decrement would send any of the tied
|
||||
variations out of bounds, the out of bounds variation is set
|
||||
to the ceiling of 255 or floor of 0, as appropriate. In this
|
||||
way, all tied variations are squashed to one edge or the
|
||||
other.
|
||||
|
||||
The top row buttons have the following keyboard accelerators:
|
||||
|
||||
-25 == Shift Left Arrow
|
||||
-10 == Control Left Arrow
|
||||
-1 == Left Arrow
|
||||
+1 == Right Arrow
|
||||
+10 == Control Right Arrow
|
||||
+25 == Shift Right Arrow
|
||||
|
||||
|
||||
Keyboard Accelerators
|
||||
|
||||
Alt-w in any secondary window dismisses the window. In the main
|
||||
window it exits Pynche (except when running as a modal).
|
||||
|
||||
Alt-q in any window exits Pynche (except when running as a modal).
|
||||
|
||||
|
||||
Persistency
|
||||
|
||||
Pynche remembers various settings of options and colors between
|
||||
invocations, storing these values in a `persistent initialization
|
||||
file'. The actual location of this file is specified by the
|
||||
--initfile option (see above), and defaults to ~/.pynche.
|
||||
|
||||
When Pynche exits, it saves these values in the init file, and
|
||||
re-reads them when it starts up. There is no locking on this
|
||||
file, so if you run multiple instances of Pynche at a time, you
|
||||
may clobber the init file.
|
||||
|
||||
The actual options stored include
|
||||
|
||||
- the currently selected color
|
||||
|
||||
- all settings of checkbox and radio button options in all windows
|
||||
|
||||
- the contents of the text window, the current text selection and
|
||||
insertion point, and all current text widget element color
|
||||
settings.
|
||||
|
||||
- the name of the color database file (but not its contents)
|
||||
|
||||
You can inhibit Pynche from reading the init file by supplying the
|
||||
--ignore option on the command line. However, you cannot suppress
|
||||
the storing of the settings in the init file on Pynche exit. If
|
||||
you really want to do this, use /dev/null as the init file, using
|
||||
--initfile.
|
||||
|
||||
|
||||
Color Name Database Files
|
||||
|
||||
Pynche uses a color name database file to calculate the nearest
|
||||
color to the selected color, and to display in the Color List
|
||||
view. Several files are distributed with Pynche, described
|
||||
below. By default, the X11 color name database file is selected.
|
||||
Other files:
|
||||
|
||||
html40colors.txt -- the HTML 4.0 guaranteed color names
|
||||
|
||||
websafe.txt -- the 216 "Web-safe" colors that Netscape and MSIE
|
||||
guarantee will not be dithered. These are specified in #rrggbb
|
||||
format for both values and names
|
||||
|
||||
webcolors.txt -- The 140 color names that Tim Peters and his
|
||||
sister say NS and MSIE both understand (with some controversy over
|
||||
AliceBlue).
|
||||
|
||||
namedcolors.txt -- an alternative set of Netscape colors.
|
||||
|
||||
You can switch between files by choosing "Load palette..." from
|
||||
the "File" menu. This brings up a standard Tk file dialog.
|
||||
Choose the file you want and then click "Ok". If Pynche
|
||||
understands the format in this file, it will load the database and
|
||||
update the appropriate windows. If not, it will bring up an error
|
||||
dialog.
|
||||
|
||||
|
||||
To Do
|
||||
|
||||
Here's a brief list of things I want to do (some mythical day):
|
||||
|
||||
- Better support for resizing the top level windows
|
||||
|
||||
- More output views, e.g. color solids
|
||||
|
||||
- Have the notion of a `last color selected'; this may require a
|
||||
new output view
|
||||
|
||||
- Support setting the font in the text view
|
||||
|
||||
- Support distutils setup.py for installation
|
||||
|
||||
I'm open to suggestions!
|
||||
|
||||
|
||||
|
||||
Local Variables:
|
||||
indent-tabs-mode: nil
|
||||
End:
|
433
third_party/python/Tools/pynche/StripViewer.py
vendored
Normal file
433
third_party/python/Tools/pynche/StripViewer.py
vendored
Normal file
|
@ -0,0 +1,433 @@
|
|||
"""Strip viewer and related widgets.
|
||||
|
||||
The classes in this file implement the StripViewer shown in the top two thirds
|
||||
of the main Pynche window. It consists of three StripWidgets which display
|
||||
the variations in red, green, and blue respectively of the currently selected
|
||||
r/g/b color value.
|
||||
|
||||
Each StripWidget shows the color variations that are reachable by varying an
|
||||
axis of the currently selected color. So for example, if the color is
|
||||
|
||||
(R,G,B)=(127,163,196)
|
||||
|
||||
then the Red variations show colors from (0,163,196) to (255,163,196), the
|
||||
Green variations show colors from (127,0,196) to (127,255,196), and the Blue
|
||||
variations show colors from (127,163,0) to (127,163,255).
|
||||
|
||||
The selected color is always visible in all three StripWidgets, and in fact
|
||||
each StripWidget highlights the selected color, and has an arrow pointing to
|
||||
the selected chip, which includes the value along that particular axis.
|
||||
|
||||
Clicking on any chip in any StripWidget selects that color, and updates all
|
||||
arrows and other windows. By toggling on Update while dragging, Pynche will
|
||||
select the color under the cursor while you drag it, but be forewarned that
|
||||
this can be slow.
|
||||
"""
|
||||
|
||||
from tkinter import *
|
||||
import ColorDB
|
||||
|
||||
# Load this script into the Tcl interpreter and call it in
|
||||
# StripWidget.set_color(). This is about as fast as it can be with the
|
||||
# current _tkinter.c interface, which doesn't support Tcl Objects.
|
||||
TCLPROC = '''\
|
||||
proc setcolor {canv colors} {
|
||||
set i 1
|
||||
foreach c $colors {
|
||||
$canv itemconfigure $i -fill $c -outline $c
|
||||
incr i
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
# Tcl event types
|
||||
BTNDOWN = 4
|
||||
BTNUP = 5
|
||||
BTNDRAG = 6
|
||||
|
||||
SPACE = ' '
|
||||
|
||||
|
||||
|
||||
def constant(numchips):
|
||||
step = 255.0 / (numchips - 1)
|
||||
start = 0.0
|
||||
seq = []
|
||||
while numchips > 0:
|
||||
seq.append(int(start))
|
||||
start = start + step
|
||||
numchips = numchips - 1
|
||||
return seq
|
||||
|
||||
# red variations, green+blue = cyan constant
|
||||
def constant_red_generator(numchips, red, green, blue):
|
||||
seq = constant(numchips)
|
||||
return list(zip([red] * numchips, seq, seq))
|
||||
|
||||
# green variations, red+blue = magenta constant
|
||||
def constant_green_generator(numchips, red, green, blue):
|
||||
seq = constant(numchips)
|
||||
return list(zip(seq, [green] * numchips, seq))
|
||||
|
||||
# blue variations, red+green = yellow constant
|
||||
def constant_blue_generator(numchips, red, green, blue):
|
||||
seq = constant(numchips)
|
||||
return list(zip(seq, seq, [blue] * numchips))
|
||||
|
||||
# red variations, green+blue = cyan constant
|
||||
def constant_cyan_generator(numchips, red, green, blue):
|
||||
seq = constant(numchips)
|
||||
return list(zip(seq, [green] * numchips, [blue] * numchips))
|
||||
|
||||
# green variations, red+blue = magenta constant
|
||||
def constant_magenta_generator(numchips, red, green, blue):
|
||||
seq = constant(numchips)
|
||||
return list(zip([red] * numchips, seq, [blue] * numchips))
|
||||
|
||||
# blue variations, red+green = yellow constant
|
||||
def constant_yellow_generator(numchips, red, green, blue):
|
||||
seq = constant(numchips)
|
||||
return list(zip([red] * numchips, [green] * numchips, seq))
|
||||
|
||||
|
||||
|
||||
class LeftArrow:
|
||||
_ARROWWIDTH = 30
|
||||
_ARROWHEIGHT = 15
|
||||
_YOFFSET = 13
|
||||
_TEXTYOFFSET = 1
|
||||
_TAG = ('leftarrow',)
|
||||
|
||||
def __init__(self, canvas, x):
|
||||
self._canvas = canvas
|
||||
self.__arrow, self.__text = self._create(x)
|
||||
self.move_to(x)
|
||||
|
||||
def _create(self, x):
|
||||
arrow = self._canvas.create_line(
|
||||
x, self._ARROWHEIGHT + self._YOFFSET,
|
||||
x, self._YOFFSET,
|
||||
x + self._ARROWWIDTH, self._YOFFSET,
|
||||
arrow='first',
|
||||
width=3.0,
|
||||
tags=self._TAG)
|
||||
text = self._canvas.create_text(
|
||||
x + self._ARROWWIDTH + 13,
|
||||
self._ARROWHEIGHT - self._TEXTYOFFSET,
|
||||
tags=self._TAG,
|
||||
text='128')
|
||||
return arrow, text
|
||||
|
||||
def _x(self):
|
||||
coords = list(self._canvas.coords(self._TAG))
|
||||
assert coords
|
||||
return coords[0]
|
||||
|
||||
def move_to(self, x):
|
||||
deltax = x - self._x()
|
||||
self._canvas.move(self._TAG, deltax, 0)
|
||||
|
||||
def set_text(self, text):
|
||||
self._canvas.itemconfigure(self.__text, text=text)
|
||||
|
||||
|
||||
class RightArrow(LeftArrow):
|
||||
_TAG = ('rightarrow',)
|
||||
|
||||
def _create(self, x):
|
||||
arrow = self._canvas.create_line(
|
||||
x, self._YOFFSET,
|
||||
x + self._ARROWWIDTH, self._YOFFSET,
|
||||
x + self._ARROWWIDTH, self._ARROWHEIGHT + self._YOFFSET,
|
||||
arrow='last',
|
||||
width=3.0,
|
||||
tags=self._TAG)
|
||||
text = self._canvas.create_text(
|
||||
x - self._ARROWWIDTH + 15, # BAW: kludge
|
||||
self._ARROWHEIGHT - self._TEXTYOFFSET,
|
||||
justify=RIGHT,
|
||||
text='128',
|
||||
tags=self._TAG)
|
||||
return arrow, text
|
||||
|
||||
def _x(self):
|
||||
coords = list(self._canvas.coords(self._TAG))
|
||||
assert coords
|
||||
return coords[0] + self._ARROWWIDTH
|
||||
|
||||
|
||||
|
||||
class StripWidget:
|
||||
_CHIPHEIGHT = 50
|
||||
_CHIPWIDTH = 10
|
||||
_NUMCHIPS = 40
|
||||
|
||||
def __init__(self, switchboard,
|
||||
master = None,
|
||||
chipwidth = _CHIPWIDTH,
|
||||
chipheight = _CHIPHEIGHT,
|
||||
numchips = _NUMCHIPS,
|
||||
generator = None,
|
||||
axis = None,
|
||||
label = '',
|
||||
uwdvar = None,
|
||||
hexvar = None):
|
||||
# instance variables
|
||||
self.__generator = generator
|
||||
self.__axis = axis
|
||||
self.__numchips = numchips
|
||||
assert self.__axis in (0, 1, 2)
|
||||
self.__uwd = uwdvar
|
||||
self.__hexp = hexvar
|
||||
# the last chip selected
|
||||
self.__lastchip = None
|
||||
self.__sb = switchboard
|
||||
|
||||
canvaswidth = numchips * (chipwidth + 1)
|
||||
canvasheight = chipheight + 43 # BAW: Kludge
|
||||
|
||||
# create the canvas and pack it
|
||||
canvas = self.__canvas = Canvas(master,
|
||||
width=canvaswidth,
|
||||
height=canvasheight,
|
||||
## borderwidth=2,
|
||||
## relief=GROOVE
|
||||
)
|
||||
|
||||
canvas.pack()
|
||||
canvas.bind('<ButtonPress-1>', self.__select_chip)
|
||||
canvas.bind('<ButtonRelease-1>', self.__select_chip)
|
||||
canvas.bind('<B1-Motion>', self.__select_chip)
|
||||
|
||||
# Load a proc into the Tcl interpreter. This is used in the
|
||||
# set_color() method to speed up setting the chip colors.
|
||||
canvas.tk.eval(TCLPROC)
|
||||
|
||||
# create the color strip
|
||||
chips = self.__chips = []
|
||||
x = 1
|
||||
y = 30
|
||||
tags = ('chip',)
|
||||
for c in range(self.__numchips):
|
||||
color = 'grey'
|
||||
canvas.create_rectangle(
|
||||
x, y, x+chipwidth, y+chipheight,
|
||||
fill=color, outline=color,
|
||||
tags=tags)
|
||||
x = x + chipwidth + 1 # for outline
|
||||
chips.append(color)
|
||||
|
||||
# create the strip label
|
||||
self.__label = canvas.create_text(
|
||||
3, y + chipheight + 8,
|
||||
text=label,
|
||||
anchor=W)
|
||||
|
||||
# create the arrow and text item
|
||||
chipx = self.__arrow_x(0)
|
||||
self.__leftarrow = LeftArrow(canvas, chipx)
|
||||
|
||||
chipx = self.__arrow_x(len(chips) - 1)
|
||||
self.__rightarrow = RightArrow(canvas, chipx)
|
||||
|
||||
def __arrow_x(self, chipnum):
|
||||
coords = self.__canvas.coords(chipnum+1)
|
||||
assert coords
|
||||
x0, y0, x1, y1 = coords
|
||||
return (x1 + x0) / 2.0
|
||||
|
||||
# Invoked when one of the chips is clicked. This should just tell the
|
||||
# switchboard to set the color on all the output components
|
||||
def __select_chip(self, event=None):
|
||||
x = event.x
|
||||
y = event.y
|
||||
canvas = self.__canvas
|
||||
chip = canvas.find_overlapping(x, y, x, y)
|
||||
if chip and (1 <= chip[0] <= self.__numchips):
|
||||
color = self.__chips[chip[0]-1]
|
||||
red, green, blue = ColorDB.rrggbb_to_triplet(color)
|
||||
etype = int(event.type)
|
||||
if (etype == BTNUP or self.__uwd.get()):
|
||||
# update everyone
|
||||
self.__sb.update_views(red, green, blue)
|
||||
else:
|
||||
# just track the arrows
|
||||
self.__trackarrow(chip[0], (red, green, blue))
|
||||
|
||||
def __trackarrow(self, chip, rgbtuple):
|
||||
# invert the last chip
|
||||
if self.__lastchip is not None:
|
||||
color = self.__canvas.itemcget(self.__lastchip, 'fill')
|
||||
self.__canvas.itemconfigure(self.__lastchip, outline=color)
|
||||
self.__lastchip = chip
|
||||
# get the arrow's text
|
||||
coloraxis = rgbtuple[self.__axis]
|
||||
if self.__hexp.get():
|
||||
# hex
|
||||
text = hex(coloraxis)
|
||||
else:
|
||||
# decimal
|
||||
text = repr(coloraxis)
|
||||
# move the arrow, and set its text
|
||||
if coloraxis <= 128:
|
||||
# use the left arrow
|
||||
self.__leftarrow.set_text(text)
|
||||
self.__leftarrow.move_to(self.__arrow_x(chip-1))
|
||||
self.__rightarrow.move_to(-100)
|
||||
else:
|
||||
# use the right arrow
|
||||
self.__rightarrow.set_text(text)
|
||||
self.__rightarrow.move_to(self.__arrow_x(chip-1))
|
||||
self.__leftarrow.move_to(-100)
|
||||
# and set the chip's outline
|
||||
brightness = ColorDB.triplet_to_brightness(rgbtuple)
|
||||
if brightness <= 128:
|
||||
outline = 'white'
|
||||
else:
|
||||
outline = 'black'
|
||||
self.__canvas.itemconfigure(chip, outline=outline)
|
||||
|
||||
|
||||
def update_yourself(self, red, green, blue):
|
||||
assert self.__generator
|
||||
i = 1
|
||||
chip = 0
|
||||
chips = self.__chips = []
|
||||
tk = self.__canvas.tk
|
||||
# get the red, green, and blue components for all chips
|
||||
for t in self.__generator(self.__numchips, red, green, blue):
|
||||
rrggbb = ColorDB.triplet_to_rrggbb(t)
|
||||
chips.append(rrggbb)
|
||||
tred, tgreen, tblue = t
|
||||
if tred <= red and tgreen <= green and tblue <= blue:
|
||||
chip = i
|
||||
i = i + 1
|
||||
# call the raw tcl script
|
||||
colors = SPACE.join(chips)
|
||||
tk.eval('setcolor %s {%s}' % (self.__canvas._w, colors))
|
||||
# move the arrows around
|
||||
self.__trackarrow(chip, (red, green, blue))
|
||||
|
||||
def set(self, label, generator):
|
||||
self.__canvas.itemconfigure(self.__label, text=label)
|
||||
self.__generator = generator
|
||||
|
||||
|
||||
class StripViewer:
|
||||
def __init__(self, switchboard, master=None):
|
||||
self.__sb = switchboard
|
||||
optiondb = switchboard.optiondb()
|
||||
# create a frame inside the master.
|
||||
frame = Frame(master, relief=RAISED, borderwidth=1)
|
||||
frame.grid(row=1, column=0, columnspan=2, sticky='NSEW')
|
||||
# create the options to be used later
|
||||
uwd = self.__uwdvar = BooleanVar()
|
||||
uwd.set(optiondb.get('UPWHILEDRAG', 0))
|
||||
hexp = self.__hexpvar = BooleanVar()
|
||||
hexp.set(optiondb.get('HEXSTRIP', 0))
|
||||
# create the red, green, blue strips inside their own frame
|
||||
frame1 = Frame(frame)
|
||||
frame1.pack(expand=YES, fill=BOTH)
|
||||
self.__reds = StripWidget(switchboard, frame1,
|
||||
generator=constant_cyan_generator,
|
||||
axis=0,
|
||||
label='Red Variations',
|
||||
uwdvar=uwd, hexvar=hexp)
|
||||
|
||||
self.__greens = StripWidget(switchboard, frame1,
|
||||
generator=constant_magenta_generator,
|
||||
axis=1,
|
||||
label='Green Variations',
|
||||
uwdvar=uwd, hexvar=hexp)
|
||||
|
||||
self.__blues = StripWidget(switchboard, frame1,
|
||||
generator=constant_yellow_generator,
|
||||
axis=2,
|
||||
label='Blue Variations',
|
||||
uwdvar=uwd, hexvar=hexp)
|
||||
|
||||
# create a frame to contain the controls
|
||||
frame2 = Frame(frame)
|
||||
frame2.pack(expand=YES, fill=BOTH)
|
||||
frame2.columnconfigure(0, weight=20)
|
||||
frame2.columnconfigure(2, weight=20)
|
||||
|
||||
padx = 8
|
||||
|
||||
# create the black button
|
||||
blackbtn = Button(frame2,
|
||||
text='Black',
|
||||
command=self.__toblack)
|
||||
blackbtn.grid(row=0, column=0, rowspan=2, sticky=W, padx=padx)
|
||||
|
||||
# create the controls
|
||||
uwdbtn = Checkbutton(frame2,
|
||||
text='Update while dragging',
|
||||
variable=uwd)
|
||||
uwdbtn.grid(row=0, column=1, sticky=W)
|
||||
hexbtn = Checkbutton(frame2,
|
||||
text='Hexadecimal',
|
||||
variable=hexp,
|
||||
command=self.__togglehex)
|
||||
hexbtn.grid(row=1, column=1, sticky=W)
|
||||
|
||||
# XXX: ignore this feature for now; it doesn't work quite right yet
|
||||
|
||||
## gentypevar = self.__gentypevar = IntVar()
|
||||
## self.__variations = Radiobutton(frame,
|
||||
## text='Variations',
|
||||
## variable=gentypevar,
|
||||
## value=0,
|
||||
## command=self.__togglegentype)
|
||||
## self.__variations.grid(row=0, column=1, sticky=W)
|
||||
## self.__constants = Radiobutton(frame,
|
||||
## text='Constants',
|
||||
## variable=gentypevar,
|
||||
## value=1,
|
||||
## command=self.__togglegentype)
|
||||
## self.__constants.grid(row=1, column=1, sticky=W)
|
||||
|
||||
# create the white button
|
||||
whitebtn = Button(frame2,
|
||||
text='White',
|
||||
command=self.__towhite)
|
||||
whitebtn.grid(row=0, column=2, rowspan=2, sticky=E, padx=padx)
|
||||
|
||||
def update_yourself(self, red, green, blue):
|
||||
self.__reds.update_yourself(red, green, blue)
|
||||
self.__greens.update_yourself(red, green, blue)
|
||||
self.__blues.update_yourself(red, green, blue)
|
||||
|
||||
def __togglehex(self, event=None):
|
||||
red, green, blue = self.__sb.current_rgb()
|
||||
self.update_yourself(red, green, blue)
|
||||
|
||||
## def __togglegentype(self, event=None):
|
||||
## which = self.__gentypevar.get()
|
||||
## if which == 0:
|
||||
## self.__reds.set(label='Red Variations',
|
||||
## generator=constant_cyan_generator)
|
||||
## self.__greens.set(label='Green Variations',
|
||||
## generator=constant_magenta_generator)
|
||||
## self.__blues.set(label='Blue Variations',
|
||||
## generator=constant_yellow_generator)
|
||||
## elif which == 1:
|
||||
## self.__reds.set(label='Red Constant',
|
||||
## generator=constant_red_generator)
|
||||
## self.__greens.set(label='Green Constant',
|
||||
## generator=constant_green_generator)
|
||||
## self.__blues.set(label='Blue Constant',
|
||||
## generator=constant_blue_generator)
|
||||
## else:
|
||||
## assert 0
|
||||
## self.__sb.update_views_current()
|
||||
|
||||
def __toblack(self, event=None):
|
||||
self.__sb.update_views(0, 0, 0)
|
||||
|
||||
def __towhite(self, event=None):
|
||||
self.__sb.update_views(255, 255, 255)
|
||||
|
||||
def save_options(self, optiondb):
|
||||
optiondb['UPWHILEDRAG'] = self.__uwdvar.get()
|
||||
optiondb['HEXSTRIP'] = self.__hexpvar.get()
|
138
third_party/python/Tools/pynche/Switchboard.py
vendored
Normal file
138
third_party/python/Tools/pynche/Switchboard.py
vendored
Normal file
|
@ -0,0 +1,138 @@
|
|||
"""Switchboard class.
|
||||
|
||||
This class is used to coordinate updates among all Viewers. Every Viewer must
|
||||
conform to the following interface:
|
||||
|
||||
- it must include a method called update_yourself() which takes three
|
||||
arguments; the red, green, and blue values of the selected color.
|
||||
|
||||
- When a Viewer selects a color and wishes to update all other Views, it
|
||||
should call update_views() on the Switchboard object. Note that the
|
||||
Viewer typically does *not* update itself before calling update_views(),
|
||||
since this would cause it to get updated twice.
|
||||
|
||||
Optionally, Viewers can also implement:
|
||||
|
||||
- save_options() which takes an optiondb (a dictionary). Store into this
|
||||
dictionary any values the Viewer wants to save in the persistent
|
||||
~/.pynche file. This dictionary is saved using marshal. The namespace
|
||||
for the keys is ad-hoc; make sure you don't clobber some other Viewer's
|
||||
keys!
|
||||
|
||||
- withdraw() which takes no arguments. This is called when Pynche is
|
||||
unmapped. All Viewers should implement this.
|
||||
|
||||
- colordb_changed() which takes a single argument, an instance of
|
||||
ColorDB. This is called whenever the color name database is changed and
|
||||
gives a chance for the Viewers to do something on those events. See
|
||||
ListViewer for details.
|
||||
|
||||
External Viewers are found dynamically. Viewer modules should have names such
|
||||
as FooViewer.py. If such a named module has a module global variable called
|
||||
ADDTOVIEW and this variable is true, the Viewer will be added dynamically to
|
||||
the `View' menu. ADDTOVIEW contains a string which is used as the menu item
|
||||
to display the Viewer (one kludge: if the string contains a `%', this is used
|
||||
to indicate that the next character will get an underline in the menu,
|
||||
otherwise the first character is underlined).
|
||||
|
||||
FooViewer.py should contain a class called FooViewer, and its constructor
|
||||
should take two arguments, an instance of Switchboard, and optionally a Tk
|
||||
master window.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import marshal
|
||||
|
||||
|
||||
|
||||
class Switchboard:
|
||||
def __init__(self, initfile):
|
||||
self.__initfile = initfile
|
||||
self.__colordb = None
|
||||
self.__optiondb = {}
|
||||
self.__views = []
|
||||
self.__red = 0
|
||||
self.__green = 0
|
||||
self.__blue = 0
|
||||
self.__canceled = 0
|
||||
# read the initialization file
|
||||
fp = None
|
||||
if initfile:
|
||||
try:
|
||||
try:
|
||||
fp = open(initfile, 'rb')
|
||||
self.__optiondb = marshal.load(fp)
|
||||
if not isinstance(self.__optiondb, dict):
|
||||
print('Problem reading options from file:', initfile,
|
||||
file=sys.stderr)
|
||||
self.__optiondb = {}
|
||||
except (IOError, EOFError, ValueError):
|
||||
pass
|
||||
finally:
|
||||
if fp:
|
||||
fp.close()
|
||||
|
||||
def add_view(self, view):
|
||||
self.__views.append(view)
|
||||
|
||||
def update_views(self, red, green, blue):
|
||||
self.__red = red
|
||||
self.__green = green
|
||||
self.__blue = blue
|
||||
for v in self.__views:
|
||||
v.update_yourself(red, green, blue)
|
||||
|
||||
def update_views_current(self):
|
||||
self.update_views(self.__red, self.__green, self.__blue)
|
||||
|
||||
def current_rgb(self):
|
||||
return self.__red, self.__green, self.__blue
|
||||
|
||||
def colordb(self):
|
||||
return self.__colordb
|
||||
|
||||
def set_colordb(self, colordb):
|
||||
self.__colordb = colordb
|
||||
for v in self.__views:
|
||||
if hasattr(v, 'colordb_changed'):
|
||||
v.colordb_changed(colordb)
|
||||
self.update_views_current()
|
||||
|
||||
def optiondb(self):
|
||||
return self.__optiondb
|
||||
|
||||
def save_views(self):
|
||||
# save the current color
|
||||
self.__optiondb['RED'] = self.__red
|
||||
self.__optiondb['GREEN'] = self.__green
|
||||
self.__optiondb['BLUE'] = self.__blue
|
||||
for v in self.__views:
|
||||
if hasattr(v, 'save_options'):
|
||||
v.save_options(self.__optiondb)
|
||||
# save the name of the file used for the color database. we'll try to
|
||||
# load this first.
|
||||
self.__optiondb['DBFILE'] = self.__colordb.filename()
|
||||
fp = None
|
||||
try:
|
||||
try:
|
||||
fp = open(self.__initfile, 'wb')
|
||||
except IOError:
|
||||
print('Cannot write options to file:', \
|
||||
self.__initfile, file=sys.stderr)
|
||||
else:
|
||||
marshal.dump(self.__optiondb, fp)
|
||||
finally:
|
||||
if fp:
|
||||
fp.close()
|
||||
|
||||
def withdraw_views(self):
|
||||
for v in self.__views:
|
||||
if hasattr(v, 'withdraw'):
|
||||
v.withdraw()
|
||||
|
||||
def canceled(self, flag=1):
|
||||
self.__canceled = flag
|
||||
|
||||
def canceled_p(self):
|
||||
return self.__canceled
|
188
third_party/python/Tools/pynche/TextViewer.py
vendored
Normal file
188
third_party/python/Tools/pynche/TextViewer.py
vendored
Normal file
|
@ -0,0 +1,188 @@
|
|||
"""TextViewer class.
|
||||
|
||||
The TextViewer allows you to see how the selected color would affect various
|
||||
characteristics of a Tk text widget. This is an output viewer only.
|
||||
|
||||
In the top part of the window is a standard text widget with some sample text
|
||||
in it. You are free to edit this text in any way you want (BAW: allow you to
|
||||
change font characteristics). If you want changes in other viewers to update
|
||||
text characteristics, turn on Track color changes.
|
||||
|
||||
To select which characteristic tracks the change, select one of the radio
|
||||
buttons in the window below. Text foreground and background affect the text
|
||||
in the window above. The Selection is what you see when you click the middle
|
||||
button and drag it through some text. The Insertion is the insertion cursor
|
||||
in the text window (which only has a background).
|
||||
"""
|
||||
|
||||
from tkinter import *
|
||||
import ColorDB
|
||||
|
||||
ADDTOVIEW = 'Text Window...'
|
||||
|
||||
|
||||
|
||||
class TextViewer:
|
||||
def __init__(self, switchboard, master=None):
|
||||
self.__sb = switchboard
|
||||
optiondb = switchboard.optiondb()
|
||||
root = self.__root = Toplevel(master, class_='Pynche')
|
||||
root.protocol('WM_DELETE_WINDOW', self.withdraw)
|
||||
root.title('Pynche Text Window')
|
||||
root.iconname('Pynche Text Window')
|
||||
root.bind('<Alt-q>', self.__quit)
|
||||
root.bind('<Alt-Q>', self.__quit)
|
||||
root.bind('<Alt-w>', self.withdraw)
|
||||
root.bind('<Alt-W>', self.withdraw)
|
||||
#
|
||||
# create the text widget
|
||||
#
|
||||
self.__text = Text(root, relief=SUNKEN,
|
||||
background=optiondb.get('TEXTBG', 'black'),
|
||||
foreground=optiondb.get('TEXTFG', 'white'),
|
||||
width=35, height=15)
|
||||
sfg = optiondb.get('TEXT_SFG')
|
||||
if sfg:
|
||||
self.__text.configure(selectforeground=sfg)
|
||||
sbg = optiondb.get('TEXT_SBG')
|
||||
if sbg:
|
||||
self.__text.configure(selectbackground=sbg)
|
||||
ibg = optiondb.get('TEXT_IBG')
|
||||
if ibg:
|
||||
self.__text.configure(insertbackground=ibg)
|
||||
self.__text.pack()
|
||||
self.__text.insert(0.0, optiondb.get('TEXT', '''\
|
||||
Insert some stuff here and play
|
||||
with the buttons below to see
|
||||
how the colors interact in
|
||||
textual displays.
|
||||
|
||||
See how the selection can also
|
||||
be affected by tickling the buttons
|
||||
and choosing a color.'''))
|
||||
insert = optiondb.get('TEXTINS')
|
||||
if insert:
|
||||
self.__text.mark_set(INSERT, insert)
|
||||
try:
|
||||
start, end = optiondb.get('TEXTSEL', (6.0, END))
|
||||
self.__text.tag_add(SEL, start, end)
|
||||
except ValueError:
|
||||
# selection wasn't set
|
||||
pass
|
||||
self.__text.focus_set()
|
||||
#
|
||||
# variables
|
||||
self.__trackp = BooleanVar()
|
||||
self.__trackp.set(optiondb.get('TRACKP', 0))
|
||||
self.__which = IntVar()
|
||||
self.__which.set(optiondb.get('WHICH', 0))
|
||||
#
|
||||
# track toggle
|
||||
self.__t = Checkbutton(root, text='Track color changes',
|
||||
variable=self.__trackp,
|
||||
relief=GROOVE,
|
||||
command=self.__toggletrack)
|
||||
self.__t.pack(fill=X, expand=YES)
|
||||
frame = self.__frame = Frame(root)
|
||||
frame.pack()
|
||||
#
|
||||
# labels
|
||||
self.__labels = []
|
||||
row = 2
|
||||
for text in ('Text:', 'Selection:', 'Insertion:'):
|
||||
l = Label(frame, text=text)
|
||||
l.grid(row=row, column=0, sticky=E)
|
||||
self.__labels.append(l)
|
||||
row += 1
|
||||
col = 1
|
||||
for text in ('Foreground', 'Background'):
|
||||
l = Label(frame, text=text)
|
||||
l.grid(row=1, column=col)
|
||||
self.__labels.append(l)
|
||||
col += 1
|
||||
#
|
||||
# radios
|
||||
self.__radios = []
|
||||
for col in (1, 2):
|
||||
for row in (2, 3, 4):
|
||||
# there is no insertforeground option
|
||||
if row==4 and col==1:
|
||||
continue
|
||||
r = Radiobutton(frame, variable=self.__which,
|
||||
value=(row-2)*2 + col-1,
|
||||
command=self.__set_color)
|
||||
r.grid(row=row, column=col)
|
||||
self.__radios.append(r)
|
||||
self.__toggletrack()
|
||||
|
||||
def __quit(self, event=None):
|
||||
self.__root.quit()
|
||||
|
||||
def withdraw(self, event=None):
|
||||
self.__root.withdraw()
|
||||
|
||||
def deiconify(self, event=None):
|
||||
self.__root.deiconify()
|
||||
|
||||
def __forceupdate(self, event=None):
|
||||
self.__sb.update_views_current()
|
||||
|
||||
def __toggletrack(self, event=None):
|
||||
if self.__trackp.get():
|
||||
state = NORMAL
|
||||
fg = self.__radios[0]['foreground']
|
||||
else:
|
||||
state = DISABLED
|
||||
fg = self.__radios[0]['disabledforeground']
|
||||
for r in self.__radios:
|
||||
r.configure(state=state)
|
||||
for l in self.__labels:
|
||||
l.configure(foreground=fg)
|
||||
|
||||
def __set_color(self, event=None):
|
||||
which = self.__which.get()
|
||||
text = self.__text
|
||||
if which == 0:
|
||||
color = text['foreground']
|
||||
elif which == 1:
|
||||
color = text['background']
|
||||
elif which == 2:
|
||||
color = text['selectforeground']
|
||||
elif which == 3:
|
||||
color = text['selectbackground']
|
||||
elif which == 5:
|
||||
color = text['insertbackground']
|
||||
try:
|
||||
red, green, blue = ColorDB.rrggbb_to_triplet(color)
|
||||
except ColorDB.BadColor:
|
||||
# must have been a color name
|
||||
red, green, blue = self.__sb.colordb().find_byname(color)
|
||||
self.__sb.update_views(red, green, blue)
|
||||
|
||||
def update_yourself(self, red, green, blue):
|
||||
if self.__trackp.get():
|
||||
colorname = ColorDB.triplet_to_rrggbb((red, green, blue))
|
||||
which = self.__which.get()
|
||||
text = self.__text
|
||||
if which == 0:
|
||||
text.configure(foreground=colorname)
|
||||
elif which == 1:
|
||||
text.configure(background=colorname)
|
||||
elif which == 2:
|
||||
text.configure(selectforeground=colorname)
|
||||
elif which == 3:
|
||||
text.configure(selectbackground=colorname)
|
||||
elif which == 5:
|
||||
text.configure(insertbackground=colorname)
|
||||
|
||||
def save_options(self, optiondb):
|
||||
optiondb['TRACKP'] = self.__trackp.get()
|
||||
optiondb['WHICH'] = self.__which.get()
|
||||
optiondb['TEXT'] = self.__text.get(0.0, 'end - 1c')
|
||||
optiondb['TEXTSEL'] = self.__text.tag_ranges(SEL)[0:2]
|
||||
optiondb['TEXTINS'] = self.__text.index(INSERT)
|
||||
optiondb['TEXTFG'] = self.__text['foreground']
|
||||
optiondb['TEXTBG'] = self.__text['background']
|
||||
optiondb['TEXT_SFG'] = self.__text['selectforeground']
|
||||
optiondb['TEXT_SBG'] = self.__text['selectbackground']
|
||||
optiondb['TEXT_IBG'] = self.__text['insertbackground']
|
161
third_party/python/Tools/pynche/TypeinViewer.py
vendored
Normal file
161
third_party/python/Tools/pynche/TypeinViewer.py
vendored
Normal file
|
@ -0,0 +1,161 @@
|
|||
"""TypeinViewer class.
|
||||
|
||||
The TypeinViewer is what you see at the lower right of the main Pynche
|
||||
widget. It contains three text entry fields, one each for red, green, blue.
|
||||
Input into these windows is highly constrained; it only allows you to enter
|
||||
values that are legal for a color axis. This usually means 0-255 for decimal
|
||||
input and 0x0 - 0xff for hex input.
|
||||
|
||||
You can toggle whether you want to view and input the values in either decimal
|
||||
or hex by clicking on Hexadecimal. By clicking on Update while typing, the
|
||||
color selection will be made on every change to the text field. Otherwise,
|
||||
you must hit Return or Tab to select the color.
|
||||
"""
|
||||
|
||||
from tkinter import *
|
||||
|
||||
|
||||
|
||||
class TypeinViewer:
|
||||
def __init__(self, switchboard, master=None):
|
||||
# non-gui ivars
|
||||
self.__sb = switchboard
|
||||
optiondb = switchboard.optiondb()
|
||||
self.__hexp = BooleanVar()
|
||||
self.__hexp.set(optiondb.get('HEXTYPE', 0))
|
||||
self.__uwtyping = BooleanVar()
|
||||
self.__uwtyping.set(optiondb.get('UPWHILETYPE', 0))
|
||||
# create the gui
|
||||
self.__frame = Frame(master, relief=RAISED, borderwidth=1)
|
||||
self.__frame.grid(row=3, column=1, sticky='NSEW')
|
||||
# Red
|
||||
self.__xl = Label(self.__frame, text='Red:')
|
||||
self.__xl.grid(row=0, column=0, sticky=E)
|
||||
subframe = Frame(self.__frame)
|
||||
subframe.grid(row=0, column=1)
|
||||
self.__xox = Label(subframe, text='0x')
|
||||
self.__xox.grid(row=0, column=0, sticky=E)
|
||||
self.__xox['font'] = 'courier'
|
||||
self.__x = Entry(subframe, width=3)
|
||||
self.__x.grid(row=0, column=1)
|
||||
self.__x.bindtags(self.__x.bindtags() + ('Normalize', 'Update'))
|
||||
self.__x.bind_class('Normalize', '<Key>', self.__normalize)
|
||||
self.__x.bind_class('Update' , '<Key>', self.__maybeupdate)
|
||||
# Green
|
||||
self.__yl = Label(self.__frame, text='Green:')
|
||||
self.__yl.grid(row=1, column=0, sticky=E)
|
||||
subframe = Frame(self.__frame)
|
||||
subframe.grid(row=1, column=1)
|
||||
self.__yox = Label(subframe, text='0x')
|
||||
self.__yox.grid(row=0, column=0, sticky=E)
|
||||
self.__yox['font'] = 'courier'
|
||||
self.__y = Entry(subframe, width=3)
|
||||
self.__y.grid(row=0, column=1)
|
||||
self.__y.bindtags(self.__y.bindtags() + ('Normalize', 'Update'))
|
||||
# Blue
|
||||
self.__zl = Label(self.__frame, text='Blue:')
|
||||
self.__zl.grid(row=2, column=0, sticky=E)
|
||||
subframe = Frame(self.__frame)
|
||||
subframe.grid(row=2, column=1)
|
||||
self.__zox = Label(subframe, text='0x')
|
||||
self.__zox.grid(row=0, column=0, sticky=E)
|
||||
self.__zox['font'] = 'courier'
|
||||
self.__z = Entry(subframe, width=3)
|
||||
self.__z.grid(row=0, column=1)
|
||||
self.__z.bindtags(self.__z.bindtags() + ('Normalize', 'Update'))
|
||||
# Update while typing?
|
||||
self.__uwt = Checkbutton(self.__frame,
|
||||
text='Update while typing',
|
||||
variable=self.__uwtyping)
|
||||
self.__uwt.grid(row=3, column=0, columnspan=2, sticky=W)
|
||||
# Hex/Dec
|
||||
self.__hex = Checkbutton(self.__frame,
|
||||
text='Hexadecimal',
|
||||
variable=self.__hexp,
|
||||
command=self.__togglehex)
|
||||
self.__hex.grid(row=4, column=0, columnspan=2, sticky=W)
|
||||
|
||||
def __togglehex(self, event=None):
|
||||
red, green, blue = self.__sb.current_rgb()
|
||||
if self.__hexp.get():
|
||||
label = '0x'
|
||||
else:
|
||||
label = ' '
|
||||
self.__xox['text'] = label
|
||||
self.__yox['text'] = label
|
||||
self.__zox['text'] = label
|
||||
self.update_yourself(red, green, blue)
|
||||
|
||||
def __normalize(self, event=None):
|
||||
ew = event.widget
|
||||
contents = ew.get()
|
||||
icursor = ew.index(INSERT)
|
||||
if contents and contents[0] in 'xX' and self.__hexp.get():
|
||||
contents = '0' + contents
|
||||
# Figure out the contents in the current base.
|
||||
try:
|
||||
if self.__hexp.get():
|
||||
v = int(contents, 16)
|
||||
else:
|
||||
v = int(contents)
|
||||
except ValueError:
|
||||
v = None
|
||||
# If value is not legal, or empty, delete the last character inserted
|
||||
# and ring the bell. Don't ring the bell if the field is empty (it'll
|
||||
# just equal zero.
|
||||
if v is None:
|
||||
pass
|
||||
elif v < 0 or v > 255:
|
||||
i = ew.index(INSERT)
|
||||
if event.char:
|
||||
contents = contents[:i-1] + contents[i:]
|
||||
icursor -= 1
|
||||
ew.bell()
|
||||
elif self.__hexp.get():
|
||||
contents = hex(v)[2:]
|
||||
else:
|
||||
contents = int(v)
|
||||
ew.delete(0, END)
|
||||
ew.insert(0, contents)
|
||||
ew.icursor(icursor)
|
||||
|
||||
def __maybeupdate(self, event=None):
|
||||
if self.__uwtyping.get() or event.keysym in ('Return', 'Tab'):
|
||||
self.__update(event)
|
||||
|
||||
def __update(self, event=None):
|
||||
redstr = self.__x.get() or '0'
|
||||
greenstr = self.__y.get() or '0'
|
||||
bluestr = self.__z.get() or '0'
|
||||
if self.__hexp.get():
|
||||
base = 16
|
||||
else:
|
||||
base = 10
|
||||
red, green, blue = [int(x, base) for x in (redstr, greenstr, bluestr)]
|
||||
self.__sb.update_views(red, green, blue)
|
||||
|
||||
def update_yourself(self, red, green, blue):
|
||||
if self.__hexp.get():
|
||||
sred, sgreen, sblue = [hex(x)[2:] for x in (red, green, blue)]
|
||||
else:
|
||||
sred, sgreen, sblue = red, green, blue
|
||||
x, y, z = self.__x, self.__y, self.__z
|
||||
xicursor = x.index(INSERT)
|
||||
yicursor = y.index(INSERT)
|
||||
zicursor = z.index(INSERT)
|
||||
x.delete(0, END)
|
||||
y.delete(0, END)
|
||||
z.delete(0, END)
|
||||
x.insert(0, sred)
|
||||
y.insert(0, sgreen)
|
||||
z.insert(0, sblue)
|
||||
x.icursor(xicursor)
|
||||
y.icursor(yicursor)
|
||||
z.icursor(zicursor)
|
||||
|
||||
def hexp_var(self):
|
||||
return self.__hexp
|
||||
|
||||
def save_options(self, optiondb):
|
||||
optiondb['HEXTYPE'] = self.__hexp.get()
|
||||
optiondb['UPWHILETYPE'] = self.__uwtyping.get()
|
753
third_party/python/Tools/pynche/X/rgb.txt
vendored
Normal file
753
third_party/python/Tools/pynche/X/rgb.txt
vendored
Normal file
|
@ -0,0 +1,753 @@
|
|||
! $XConsortium: rgb.txt,v 10.41 94/02/20 18:39:36 rws Exp $
|
||||
255 250 250 snow
|
||||
248 248 255 ghost white
|
||||
248 248 255 GhostWhite
|
||||
245 245 245 white smoke
|
||||
245 245 245 WhiteSmoke
|
||||
220 220 220 gainsboro
|
||||
255 250 240 floral white
|
||||
255 250 240 FloralWhite
|
||||
253 245 230 old lace
|
||||
253 245 230 OldLace
|
||||
250 240 230 linen
|
||||
250 235 215 antique white
|
||||
250 235 215 AntiqueWhite
|
||||
255 239 213 papaya whip
|
||||
255 239 213 PapayaWhip
|
||||
255 235 205 blanched almond
|
||||
255 235 205 BlanchedAlmond
|
||||
255 228 196 bisque
|
||||
255 218 185 peach puff
|
||||
255 218 185 PeachPuff
|
||||
255 222 173 navajo white
|
||||
255 222 173 NavajoWhite
|
||||
255 228 181 moccasin
|
||||
255 248 220 cornsilk
|
||||
255 255 240 ivory
|
||||
255 250 205 lemon chiffon
|
||||
255 250 205 LemonChiffon
|
||||
255 245 238 seashell
|
||||
240 255 240 honeydew
|
||||
245 255 250 mint cream
|
||||
245 255 250 MintCream
|
||||
240 255 255 azure
|
||||
240 248 255 alice blue
|
||||
240 248 255 AliceBlue
|
||||
230 230 250 lavender
|
||||
255 240 245 lavender blush
|
||||
255 240 245 LavenderBlush
|
||||
255 228 225 misty rose
|
||||
255 228 225 MistyRose
|
||||
255 255 255 white
|
||||
0 0 0 black
|
||||
47 79 79 dark slate gray
|
||||
47 79 79 DarkSlateGray
|
||||
47 79 79 dark slate grey
|
||||
47 79 79 DarkSlateGrey
|
||||
105 105 105 dim gray
|
||||
105 105 105 DimGray
|
||||
105 105 105 dim grey
|
||||
105 105 105 DimGrey
|
||||
112 128 144 slate gray
|
||||
112 128 144 SlateGray
|
||||
112 128 144 slate grey
|
||||
112 128 144 SlateGrey
|
||||
119 136 153 light slate gray
|
||||
119 136 153 LightSlateGray
|
||||
119 136 153 light slate grey
|
||||
119 136 153 LightSlateGrey
|
||||
190 190 190 gray
|
||||
190 190 190 grey
|
||||
211 211 211 light grey
|
||||
211 211 211 LightGrey
|
||||
211 211 211 light gray
|
||||
211 211 211 LightGray
|
||||
25 25 112 midnight blue
|
||||
25 25 112 MidnightBlue
|
||||
0 0 128 navy
|
||||
0 0 128 navy blue
|
||||
0 0 128 NavyBlue
|
||||
100 149 237 cornflower blue
|
||||
100 149 237 CornflowerBlue
|
||||
72 61 139 dark slate blue
|
||||
72 61 139 DarkSlateBlue
|
||||
106 90 205 slate blue
|
||||
106 90 205 SlateBlue
|
||||
123 104 238 medium slate blue
|
||||
123 104 238 MediumSlateBlue
|
||||
132 112 255 light slate blue
|
||||
132 112 255 LightSlateBlue
|
||||
0 0 205 medium blue
|
||||
0 0 205 MediumBlue
|
||||
65 105 225 royal blue
|
||||
65 105 225 RoyalBlue
|
||||
0 0 255 blue
|
||||
30 144 255 dodger blue
|
||||
30 144 255 DodgerBlue
|
||||
0 191 255 deep sky blue
|
||||
0 191 255 DeepSkyBlue
|
||||
135 206 235 sky blue
|
||||
135 206 235 SkyBlue
|
||||
135 206 250 light sky blue
|
||||
135 206 250 LightSkyBlue
|
||||
70 130 180 steel blue
|
||||
70 130 180 SteelBlue
|
||||
176 196 222 light steel blue
|
||||
176 196 222 LightSteelBlue
|
||||
173 216 230 light blue
|
||||
173 216 230 LightBlue
|
||||
176 224 230 powder blue
|
||||
176 224 230 PowderBlue
|
||||
175 238 238 pale turquoise
|
||||
175 238 238 PaleTurquoise
|
||||
0 206 209 dark turquoise
|
||||
0 206 209 DarkTurquoise
|
||||
72 209 204 medium turquoise
|
||||
72 209 204 MediumTurquoise
|
||||
64 224 208 turquoise
|
||||
0 255 255 cyan
|
||||
224 255 255 light cyan
|
||||
224 255 255 LightCyan
|
||||
95 158 160 cadet blue
|
||||
95 158 160 CadetBlue
|
||||
102 205 170 medium aquamarine
|
||||
102 205 170 MediumAquamarine
|
||||
127 255 212 aquamarine
|
||||
0 100 0 dark green
|
||||
0 100 0 DarkGreen
|
||||
85 107 47 dark olive green
|
||||
85 107 47 DarkOliveGreen
|
||||
143 188 143 dark sea green
|
||||
143 188 143 DarkSeaGreen
|
||||
46 139 87 sea green
|
||||
46 139 87 SeaGreen
|
||||
60 179 113 medium sea green
|
||||
60 179 113 MediumSeaGreen
|
||||
32 178 170 light sea green
|
||||
32 178 170 LightSeaGreen
|
||||
152 251 152 pale green
|
||||
152 251 152 PaleGreen
|
||||
0 255 127 spring green
|
||||
0 255 127 SpringGreen
|
||||
124 252 0 lawn green
|
||||
124 252 0 LawnGreen
|
||||
0 255 0 green
|
||||
127 255 0 chartreuse
|
||||
0 250 154 medium spring green
|
||||
0 250 154 MediumSpringGreen
|
||||
173 255 47 green yellow
|
||||
173 255 47 GreenYellow
|
||||
50 205 50 lime green
|
||||
50 205 50 LimeGreen
|
||||
154 205 50 yellow green
|
||||
154 205 50 YellowGreen
|
||||
34 139 34 forest green
|
||||
34 139 34 ForestGreen
|
||||
107 142 35 olive drab
|
||||
107 142 35 OliveDrab
|
||||
189 183 107 dark khaki
|
||||
189 183 107 DarkKhaki
|
||||
240 230 140 khaki
|
||||
238 232 170 pale goldenrod
|
||||
238 232 170 PaleGoldenrod
|
||||
250 250 210 light goldenrod yellow
|
||||
250 250 210 LightGoldenrodYellow
|
||||
255 255 224 light yellow
|
||||
255 255 224 LightYellow
|
||||
255 255 0 yellow
|
||||
255 215 0 gold
|
||||
238 221 130 light goldenrod
|
||||
238 221 130 LightGoldenrod
|
||||
218 165 32 goldenrod
|
||||
184 134 11 dark goldenrod
|
||||
184 134 11 DarkGoldenrod
|
||||
188 143 143 rosy brown
|
||||
188 143 143 RosyBrown
|
||||
205 92 92 indian red
|
||||
205 92 92 IndianRed
|
||||
139 69 19 saddle brown
|
||||
139 69 19 SaddleBrown
|
||||
160 82 45 sienna
|
||||
205 133 63 peru
|
||||
222 184 135 burlywood
|
||||
245 245 220 beige
|
||||
245 222 179 wheat
|
||||
244 164 96 sandy brown
|
||||
244 164 96 SandyBrown
|
||||
210 180 140 tan
|
||||
210 105 30 chocolate
|
||||
178 34 34 firebrick
|
||||
165 42 42 brown
|
||||
233 150 122 dark salmon
|
||||
233 150 122 DarkSalmon
|
||||
250 128 114 salmon
|
||||
255 160 122 light salmon
|
||||
255 160 122 LightSalmon
|
||||
255 165 0 orange
|
||||
255 140 0 dark orange
|
||||
255 140 0 DarkOrange
|
||||
255 127 80 coral
|
||||
240 128 128 light coral
|
||||
240 128 128 LightCoral
|
||||
255 99 71 tomato
|
||||
255 69 0 orange red
|
||||
255 69 0 OrangeRed
|
||||
255 0 0 red
|
||||
255 105 180 hot pink
|
||||
255 105 180 HotPink
|
||||
255 20 147 deep pink
|
||||
255 20 147 DeepPink
|
||||
255 192 203 pink
|
||||
255 182 193 light pink
|
||||
255 182 193 LightPink
|
||||
219 112 147 pale violet red
|
||||
219 112 147 PaleVioletRed
|
||||
176 48 96 maroon
|
||||
199 21 133 medium violet red
|
||||
199 21 133 MediumVioletRed
|
||||
208 32 144 violet red
|
||||
208 32 144 VioletRed
|
||||
255 0 255 magenta
|
||||
238 130 238 violet
|
||||
221 160 221 plum
|
||||
218 112 214 orchid
|
||||
186 85 211 medium orchid
|
||||
186 85 211 MediumOrchid
|
||||
153 50 204 dark orchid
|
||||
153 50 204 DarkOrchid
|
||||
148 0 211 dark violet
|
||||
148 0 211 DarkViolet
|
||||
138 43 226 blue violet
|
||||
138 43 226 BlueViolet
|
||||
160 32 240 purple
|
||||
147 112 219 medium purple
|
||||
147 112 219 MediumPurple
|
||||
216 191 216 thistle
|
||||
255 250 250 snow1
|
||||
238 233 233 snow2
|
||||
205 201 201 snow3
|
||||
139 137 137 snow4
|
||||
255 245 238 seashell1
|
||||
238 229 222 seashell2
|
||||
205 197 191 seashell3
|
||||
139 134 130 seashell4
|
||||
255 239 219 AntiqueWhite1
|
||||
238 223 204 AntiqueWhite2
|
||||
205 192 176 AntiqueWhite3
|
||||
139 131 120 AntiqueWhite4
|
||||
255 228 196 bisque1
|
||||
238 213 183 bisque2
|
||||
205 183 158 bisque3
|
||||
139 125 107 bisque4
|
||||
255 218 185 PeachPuff1
|
||||
238 203 173 PeachPuff2
|
||||
205 175 149 PeachPuff3
|
||||
139 119 101 PeachPuff4
|
||||
255 222 173 NavajoWhite1
|
||||
238 207 161 NavajoWhite2
|
||||
205 179 139 NavajoWhite3
|
||||
139 121 94 NavajoWhite4
|
||||
255 250 205 LemonChiffon1
|
||||
238 233 191 LemonChiffon2
|
||||
205 201 165 LemonChiffon3
|
||||
139 137 112 LemonChiffon4
|
||||
255 248 220 cornsilk1
|
||||
238 232 205 cornsilk2
|
||||
205 200 177 cornsilk3
|
||||
139 136 120 cornsilk4
|
||||
255 255 240 ivory1
|
||||
238 238 224 ivory2
|
||||
205 205 193 ivory3
|
||||
139 139 131 ivory4
|
||||
240 255 240 honeydew1
|
||||
224 238 224 honeydew2
|
||||
193 205 193 honeydew3
|
||||
131 139 131 honeydew4
|
||||
255 240 245 LavenderBlush1
|
||||
238 224 229 LavenderBlush2
|
||||
205 193 197 LavenderBlush3
|
||||
139 131 134 LavenderBlush4
|
||||
255 228 225 MistyRose1
|
||||
238 213 210 MistyRose2
|
||||
205 183 181 MistyRose3
|
||||
139 125 123 MistyRose4
|
||||
240 255 255 azure1
|
||||
224 238 238 azure2
|
||||
193 205 205 azure3
|
||||
131 139 139 azure4
|
||||
131 111 255 SlateBlue1
|
||||
122 103 238 SlateBlue2
|
||||
105 89 205 SlateBlue3
|
||||
71 60 139 SlateBlue4
|
||||
72 118 255 RoyalBlue1
|
||||
67 110 238 RoyalBlue2
|
||||
58 95 205 RoyalBlue3
|
||||
39 64 139 RoyalBlue4
|
||||
0 0 255 blue1
|
||||
0 0 238 blue2
|
||||
0 0 205 blue3
|
||||
0 0 139 blue4
|
||||
30 144 255 DodgerBlue1
|
||||
28 134 238 DodgerBlue2
|
||||
24 116 205 DodgerBlue3
|
||||
16 78 139 DodgerBlue4
|
||||
99 184 255 SteelBlue1
|
||||
92 172 238 SteelBlue2
|
||||
79 148 205 SteelBlue3
|
||||
54 100 139 SteelBlue4
|
||||
0 191 255 DeepSkyBlue1
|
||||
0 178 238 DeepSkyBlue2
|
||||
0 154 205 DeepSkyBlue3
|
||||
0 104 139 DeepSkyBlue4
|
||||
135 206 255 SkyBlue1
|
||||
126 192 238 SkyBlue2
|
||||
108 166 205 SkyBlue3
|
||||
74 112 139 SkyBlue4
|
||||
176 226 255 LightSkyBlue1
|
||||
164 211 238 LightSkyBlue2
|
||||
141 182 205 LightSkyBlue3
|
||||
96 123 139 LightSkyBlue4
|
||||
198 226 255 SlateGray1
|
||||
185 211 238 SlateGray2
|
||||
159 182 205 SlateGray3
|
||||
108 123 139 SlateGray4
|
||||
202 225 255 LightSteelBlue1
|
||||
188 210 238 LightSteelBlue2
|
||||
162 181 205 LightSteelBlue3
|
||||
110 123 139 LightSteelBlue4
|
||||
191 239 255 LightBlue1
|
||||
178 223 238 LightBlue2
|
||||
154 192 205 LightBlue3
|
||||
104 131 139 LightBlue4
|
||||
224 255 255 LightCyan1
|
||||
209 238 238 LightCyan2
|
||||
180 205 205 LightCyan3
|
||||
122 139 139 LightCyan4
|
||||
187 255 255 PaleTurquoise1
|
||||
174 238 238 PaleTurquoise2
|
||||
150 205 205 PaleTurquoise3
|
||||
102 139 139 PaleTurquoise4
|
||||
152 245 255 CadetBlue1
|
||||
142 229 238 CadetBlue2
|
||||
122 197 205 CadetBlue3
|
||||
83 134 139 CadetBlue4
|
||||
0 245 255 turquoise1
|
||||
0 229 238 turquoise2
|
||||
0 197 205 turquoise3
|
||||
0 134 139 turquoise4
|
||||
0 255 255 cyan1
|
||||
0 238 238 cyan2
|
||||
0 205 205 cyan3
|
||||
0 139 139 cyan4
|
||||
151 255 255 DarkSlateGray1
|
||||
141 238 238 DarkSlateGray2
|
||||
121 205 205 DarkSlateGray3
|
||||
82 139 139 DarkSlateGray4
|
||||
127 255 212 aquamarine1
|
||||
118 238 198 aquamarine2
|
||||
102 205 170 aquamarine3
|
||||
69 139 116 aquamarine4
|
||||
193 255 193 DarkSeaGreen1
|
||||
180 238 180 DarkSeaGreen2
|
||||
155 205 155 DarkSeaGreen3
|
||||
105 139 105 DarkSeaGreen4
|
||||
84 255 159 SeaGreen1
|
||||
78 238 148 SeaGreen2
|
||||
67 205 128 SeaGreen3
|
||||
46 139 87 SeaGreen4
|
||||
154 255 154 PaleGreen1
|
||||
144 238 144 PaleGreen2
|
||||
124 205 124 PaleGreen3
|
||||
84 139 84 PaleGreen4
|
||||
0 255 127 SpringGreen1
|
||||
0 238 118 SpringGreen2
|
||||
0 205 102 SpringGreen3
|
||||
0 139 69 SpringGreen4
|
||||
0 255 0 green1
|
||||
0 238 0 green2
|
||||
0 205 0 green3
|
||||
0 139 0 green4
|
||||
127 255 0 chartreuse1
|
||||
118 238 0 chartreuse2
|
||||
102 205 0 chartreuse3
|
||||
69 139 0 chartreuse4
|
||||
192 255 62 OliveDrab1
|
||||
179 238 58 OliveDrab2
|
||||
154 205 50 OliveDrab3
|
||||
105 139 34 OliveDrab4
|
||||
202 255 112 DarkOliveGreen1
|
||||
188 238 104 DarkOliveGreen2
|
||||
162 205 90 DarkOliveGreen3
|
||||
110 139 61 DarkOliveGreen4
|
||||
255 246 143 khaki1
|
||||
238 230 133 khaki2
|
||||
205 198 115 khaki3
|
||||
139 134 78 khaki4
|
||||
255 236 139 LightGoldenrod1
|
||||
238 220 130 LightGoldenrod2
|
||||
205 190 112 LightGoldenrod3
|
||||
139 129 76 LightGoldenrod4
|
||||
255 255 224 LightYellow1
|
||||
238 238 209 LightYellow2
|
||||
205 205 180 LightYellow3
|
||||
139 139 122 LightYellow4
|
||||
255 255 0 yellow1
|
||||
238 238 0 yellow2
|
||||
205 205 0 yellow3
|
||||
139 139 0 yellow4
|
||||
255 215 0 gold1
|
||||
238 201 0 gold2
|
||||
205 173 0 gold3
|
||||
139 117 0 gold4
|
||||
255 193 37 goldenrod1
|
||||
238 180 34 goldenrod2
|
||||
205 155 29 goldenrod3
|
||||
139 105 20 goldenrod4
|
||||
255 185 15 DarkGoldenrod1
|
||||
238 173 14 DarkGoldenrod2
|
||||
205 149 12 DarkGoldenrod3
|
||||
139 101 8 DarkGoldenrod4
|
||||
255 193 193 RosyBrown1
|
||||
238 180 180 RosyBrown2
|
||||
205 155 155 RosyBrown3
|
||||
139 105 105 RosyBrown4
|
||||
255 106 106 IndianRed1
|
||||
238 99 99 IndianRed2
|
||||
205 85 85 IndianRed3
|
||||
139 58 58 IndianRed4
|
||||
255 130 71 sienna1
|
||||
238 121 66 sienna2
|
||||
205 104 57 sienna3
|
||||
139 71 38 sienna4
|
||||
255 211 155 burlywood1
|
||||
238 197 145 burlywood2
|
||||
205 170 125 burlywood3
|
||||
139 115 85 burlywood4
|
||||
255 231 186 wheat1
|
||||
238 216 174 wheat2
|
||||
205 186 150 wheat3
|
||||
139 126 102 wheat4
|
||||
255 165 79 tan1
|
||||
238 154 73 tan2
|
||||
205 133 63 tan3
|
||||
139 90 43 tan4
|
||||
255 127 36 chocolate1
|
||||
238 118 33 chocolate2
|
||||
205 102 29 chocolate3
|
||||
139 69 19 chocolate4
|
||||
255 48 48 firebrick1
|
||||
238 44 44 firebrick2
|
||||
205 38 38 firebrick3
|
||||
139 26 26 firebrick4
|
||||
255 64 64 brown1
|
||||
238 59 59 brown2
|
||||
205 51 51 brown3
|
||||
139 35 35 brown4
|
||||
255 140 105 salmon1
|
||||
238 130 98 salmon2
|
||||
205 112 84 salmon3
|
||||
139 76 57 salmon4
|
||||
255 160 122 LightSalmon1
|
||||
238 149 114 LightSalmon2
|
||||
205 129 98 LightSalmon3
|
||||
139 87 66 LightSalmon4
|
||||
255 165 0 orange1
|
||||
238 154 0 orange2
|
||||
205 133 0 orange3
|
||||
139 90 0 orange4
|
||||
255 127 0 DarkOrange1
|
||||
238 118 0 DarkOrange2
|
||||
205 102 0 DarkOrange3
|
||||
139 69 0 DarkOrange4
|
||||
255 114 86 coral1
|
||||
238 106 80 coral2
|
||||
205 91 69 coral3
|
||||
139 62 47 coral4
|
||||
255 99 71 tomato1
|
||||
238 92 66 tomato2
|
||||
205 79 57 tomato3
|
||||
139 54 38 tomato4
|
||||
255 69 0 OrangeRed1
|
||||
238 64 0 OrangeRed2
|
||||
205 55 0 OrangeRed3
|
||||
139 37 0 OrangeRed4
|
||||
255 0 0 red1
|
||||
238 0 0 red2
|
||||
205 0 0 red3
|
||||
139 0 0 red4
|
||||
255 20 147 DeepPink1
|
||||
238 18 137 DeepPink2
|
||||
205 16 118 DeepPink3
|
||||
139 10 80 DeepPink4
|
||||
255 110 180 HotPink1
|
||||
238 106 167 HotPink2
|
||||
205 96 144 HotPink3
|
||||
139 58 98 HotPink4
|
||||
255 181 197 pink1
|
||||
238 169 184 pink2
|
||||
205 145 158 pink3
|
||||
139 99 108 pink4
|
||||
255 174 185 LightPink1
|
||||
238 162 173 LightPink2
|
||||
205 140 149 LightPink3
|
||||
139 95 101 LightPink4
|
||||
255 130 171 PaleVioletRed1
|
||||
238 121 159 PaleVioletRed2
|
||||
205 104 137 PaleVioletRed3
|
||||
139 71 93 PaleVioletRed4
|
||||
255 52 179 maroon1
|
||||
238 48 167 maroon2
|
||||
205 41 144 maroon3
|
||||
139 28 98 maroon4
|
||||
255 62 150 VioletRed1
|
||||
238 58 140 VioletRed2
|
||||
205 50 120 VioletRed3
|
||||
139 34 82 VioletRed4
|
||||
255 0 255 magenta1
|
||||
238 0 238 magenta2
|
||||
205 0 205 magenta3
|
||||
139 0 139 magenta4
|
||||
255 131 250 orchid1
|
||||
238 122 233 orchid2
|
||||
205 105 201 orchid3
|
||||
139 71 137 orchid4
|
||||
255 187 255 plum1
|
||||
238 174 238 plum2
|
||||
205 150 205 plum3
|
||||
139 102 139 plum4
|
||||
224 102 255 MediumOrchid1
|
||||
209 95 238 MediumOrchid2
|
||||
180 82 205 MediumOrchid3
|
||||
122 55 139 MediumOrchid4
|
||||
191 62 255 DarkOrchid1
|
||||
178 58 238 DarkOrchid2
|
||||
154 50 205 DarkOrchid3
|
||||
104 34 139 DarkOrchid4
|
||||
155 48 255 purple1
|
||||
145 44 238 purple2
|
||||
125 38 205 purple3
|
||||
85 26 139 purple4
|
||||
171 130 255 MediumPurple1
|
||||
159 121 238 MediumPurple2
|
||||
137 104 205 MediumPurple3
|
||||
93 71 139 MediumPurple4
|
||||
255 225 255 thistle1
|
||||
238 210 238 thistle2
|
||||
205 181 205 thistle3
|
||||
139 123 139 thistle4
|
||||
0 0 0 gray0
|
||||
0 0 0 grey0
|
||||
3 3 3 gray1
|
||||
3 3 3 grey1
|
||||
5 5 5 gray2
|
||||
5 5 5 grey2
|
||||
8 8 8 gray3
|
||||
8 8 8 grey3
|
||||
10 10 10 gray4
|
||||
10 10 10 grey4
|
||||
13 13 13 gray5
|
||||
13 13 13 grey5
|
||||
15 15 15 gray6
|
||||
15 15 15 grey6
|
||||
18 18 18 gray7
|
||||
18 18 18 grey7
|
||||
20 20 20 gray8
|
||||
20 20 20 grey8
|
||||
23 23 23 gray9
|
||||
23 23 23 grey9
|
||||
26 26 26 gray10
|
||||
26 26 26 grey10
|
||||
28 28 28 gray11
|
||||
28 28 28 grey11
|
||||
31 31 31 gray12
|
||||
31 31 31 grey12
|
||||
33 33 33 gray13
|
||||
33 33 33 grey13
|
||||
36 36 36 gray14
|
||||
36 36 36 grey14
|
||||
38 38 38 gray15
|
||||
38 38 38 grey15
|
||||
41 41 41 gray16
|
||||
41 41 41 grey16
|
||||
43 43 43 gray17
|
||||
43 43 43 grey17
|
||||
46 46 46 gray18
|
||||
46 46 46 grey18
|
||||
48 48 48 gray19
|
||||
48 48 48 grey19
|
||||
51 51 51 gray20
|
||||
51 51 51 grey20
|
||||
54 54 54 gray21
|
||||
54 54 54 grey21
|
||||
56 56 56 gray22
|
||||
56 56 56 grey22
|
||||
59 59 59 gray23
|
||||
59 59 59 grey23
|
||||
61 61 61 gray24
|
||||
61 61 61 grey24
|
||||
64 64 64 gray25
|
||||
64 64 64 grey25
|
||||
66 66 66 gray26
|
||||
66 66 66 grey26
|
||||
69 69 69 gray27
|
||||
69 69 69 grey27
|
||||
71 71 71 gray28
|
||||
71 71 71 grey28
|
||||
74 74 74 gray29
|
||||
74 74 74 grey29
|
||||
77 77 77 gray30
|
||||
77 77 77 grey30
|
||||
79 79 79 gray31
|
||||
79 79 79 grey31
|
||||
82 82 82 gray32
|
||||
82 82 82 grey32
|
||||
84 84 84 gray33
|
||||
84 84 84 grey33
|
||||
87 87 87 gray34
|
||||
87 87 87 grey34
|
||||
89 89 89 gray35
|
||||
89 89 89 grey35
|
||||
92 92 92 gray36
|
||||
92 92 92 grey36
|
||||
94 94 94 gray37
|
||||
94 94 94 grey37
|
||||
97 97 97 gray38
|
||||
97 97 97 grey38
|
||||
99 99 99 gray39
|
||||
99 99 99 grey39
|
||||
102 102 102 gray40
|
||||
102 102 102 grey40
|
||||
105 105 105 gray41
|
||||
105 105 105 grey41
|
||||
107 107 107 gray42
|
||||
107 107 107 grey42
|
||||
110 110 110 gray43
|
||||
110 110 110 grey43
|
||||
112 112 112 gray44
|
||||
112 112 112 grey44
|
||||
115 115 115 gray45
|
||||
115 115 115 grey45
|
||||
117 117 117 gray46
|
||||
117 117 117 grey46
|
||||
120 120 120 gray47
|
||||
120 120 120 grey47
|
||||
122 122 122 gray48
|
||||
122 122 122 grey48
|
||||
125 125 125 gray49
|
||||
125 125 125 grey49
|
||||
127 127 127 gray50
|
||||
127 127 127 grey50
|
||||
130 130 130 gray51
|
||||
130 130 130 grey51
|
||||
133 133 133 gray52
|
||||
133 133 133 grey52
|
||||
135 135 135 gray53
|
||||
135 135 135 grey53
|
||||
138 138 138 gray54
|
||||
138 138 138 grey54
|
||||
140 140 140 gray55
|
||||
140 140 140 grey55
|
||||
143 143 143 gray56
|
||||
143 143 143 grey56
|
||||
145 145 145 gray57
|
||||
145 145 145 grey57
|
||||
148 148 148 gray58
|
||||
148 148 148 grey58
|
||||
150 150 150 gray59
|
||||
150 150 150 grey59
|
||||
153 153 153 gray60
|
||||
153 153 153 grey60
|
||||
156 156 156 gray61
|
||||
156 156 156 grey61
|
||||
158 158 158 gray62
|
||||
158 158 158 grey62
|
||||
161 161 161 gray63
|
||||
161 161 161 grey63
|
||||
163 163 163 gray64
|
||||
163 163 163 grey64
|
||||
166 166 166 gray65
|
||||
166 166 166 grey65
|
||||
168 168 168 gray66
|
||||
168 168 168 grey66
|
||||
171 171 171 gray67
|
||||
171 171 171 grey67
|
||||
173 173 173 gray68
|
||||
173 173 173 grey68
|
||||
176 176 176 gray69
|
||||
176 176 176 grey69
|
||||
179 179 179 gray70
|
||||
179 179 179 grey70
|
||||
181 181 181 gray71
|
||||
181 181 181 grey71
|
||||
184 184 184 gray72
|
||||
184 184 184 grey72
|
||||
186 186 186 gray73
|
||||
186 186 186 grey73
|
||||
189 189 189 gray74
|
||||
189 189 189 grey74
|
||||
191 191 191 gray75
|
||||
191 191 191 grey75
|
||||
194 194 194 gray76
|
||||
194 194 194 grey76
|
||||
196 196 196 gray77
|
||||
196 196 196 grey77
|
||||
199 199 199 gray78
|
||||
199 199 199 grey78
|
||||
201 201 201 gray79
|
||||
201 201 201 grey79
|
||||
204 204 204 gray80
|
||||
204 204 204 grey80
|
||||
207 207 207 gray81
|
||||
207 207 207 grey81
|
||||
209 209 209 gray82
|
||||
209 209 209 grey82
|
||||
212 212 212 gray83
|
||||
212 212 212 grey83
|
||||
214 214 214 gray84
|
||||
214 214 214 grey84
|
||||
217 217 217 gray85
|
||||
217 217 217 grey85
|
||||
219 219 219 gray86
|
||||
219 219 219 grey86
|
||||
222 222 222 gray87
|
||||
222 222 222 grey87
|
||||
224 224 224 gray88
|
||||
224 224 224 grey88
|
||||
227 227 227 gray89
|
||||
227 227 227 grey89
|
||||
229 229 229 gray90
|
||||
229 229 229 grey90
|
||||
232 232 232 gray91
|
||||
232 232 232 grey91
|
||||
235 235 235 gray92
|
||||
235 235 235 grey92
|
||||
237 237 237 gray93
|
||||
237 237 237 grey93
|
||||
240 240 240 gray94
|
||||
240 240 240 grey94
|
||||
242 242 242 gray95
|
||||
242 242 242 grey95
|
||||
245 245 245 gray96
|
||||
245 245 245 grey96
|
||||
247 247 247 gray97
|
||||
247 247 247 grey97
|
||||
250 250 250 gray98
|
||||
250 250 250 grey98
|
||||
252 252 252 gray99
|
||||
252 252 252 grey99
|
||||
255 255 255 gray100
|
||||
255 255 255 grey100
|
||||
169 169 169 dark grey
|
||||
169 169 169 DarkGrey
|
||||
169 169 169 dark gray
|
||||
169 169 169 DarkGray
|
||||
0 0 139 dark blue
|
||||
0 0 139 DarkBlue
|
||||
0 139 139 dark cyan
|
||||
0 139 139 DarkCyan
|
||||
139 0 139 dark magenta
|
||||
139 0 139 DarkMagenta
|
||||
139 0 0 dark red
|
||||
139 0 0 DarkRed
|
||||
144 238 144 light green
|
||||
144 238 144 LightGreen
|
29
third_party/python/Tools/pynche/X/xlicense.txt
vendored
Normal file
29
third_party/python/Tools/pynche/X/xlicense.txt
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
X Window System License - X11R6.4
|
||||
|
||||
Copyright (c) 1998 The Open Group
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of The Open Group shall
|
||||
not be used in advertising or otherwise to promote the sale, use or
|
||||
other dealings in this Software without prior written authorization
|
||||
from The Open Group.
|
||||
|
||||
X Window System is a trademark of The Open Group
|
1
third_party/python/Tools/pynche/__init__.py
vendored
Normal file
1
third_party/python/Tools/pynche/__init__.py
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
# Dummy file to make this directory a package.
|
17
third_party/python/Tools/pynche/html40colors.txt
vendored
Normal file
17
third_party/python/Tools/pynche/html40colors.txt
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
# HTML 4.0 color names
|
||||
Black #000000
|
||||
Silver #c0c0c0
|
||||
Gray #808080
|
||||
White #ffffff
|
||||
Maroon #800000
|
||||
Red #ff0000
|
||||
Purple #800080
|
||||
Fuchsia #ff00ff
|
||||
Green #008000
|
||||
Lime #00ff00
|
||||
Olive #808000
|
||||
Yellow #ffff00
|
||||
Navy #000080
|
||||
Blue #0000ff
|
||||
Teal #008080
|
||||
Aqua #00ffff
|
100
third_party/python/Tools/pynche/namedcolors.txt
vendored
Normal file
100
third_party/python/Tools/pynche/namedcolors.txt
vendored
Normal file
|
@ -0,0 +1,100 @@
|
|||
# named colors from http://www.lightlink.com/xine/bells/namedcolors.html
|
||||
White #FFFFFF
|
||||
Red #FF0000
|
||||
Green #00FF00
|
||||
Blue #0000FF
|
||||
Magenta #FF00FF
|
||||
Cyan #00FFFF
|
||||
Yellow #FFFF00
|
||||
Black #000000
|
||||
Aquamarine #70DB93
|
||||
Baker's Chocolate #5C3317
|
||||
Blue Violet #9F5F9F
|
||||
Brass #B5A642
|
||||
Bright Gold #D9D919
|
||||
Brown #A62A2A
|
||||
Bronze #8C7853
|
||||
Bronze II #A67D3D
|
||||
Cadet Blue #5F9F9F
|
||||
Cool Copper #D98719
|
||||
Copper #B87333
|
||||
Coral #FF7F00
|
||||
Corn Flower Blue #42426F
|
||||
Dark Brown #5C4033
|
||||
Dark Green #2F4F2F
|
||||
Dark Green Copper #4A766E
|
||||
Dark Olive Green #4F4F2F
|
||||
Dark Orchid #9932CD
|
||||
Dark Purple #871F78
|
||||
Dark Slate Blue #6B238E
|
||||
Dark Slate Grey #2F4F4F
|
||||
Dark Tan #97694F
|
||||
Dark Turquoise #7093DB
|
||||
Dark Wood #855E42
|
||||
Dim Grey #545454
|
||||
Dusty Rose #856363
|
||||
Feldspar #D19275
|
||||
Firebrick #8E2323
|
||||
Forest Green #238E23
|
||||
Gold #CD7F32
|
||||
Goldenrod #DBDB70
|
||||
Grey #C0C0C0
|
||||
Green Copper #527F76
|
||||
Green Yellow #93DB70
|
||||
Hunter Green #215E21
|
||||
Indian Red #4E2F2F
|
||||
Khaki #9F9F5F
|
||||
Light Blue #C0D9D9
|
||||
Light Grey #A8A8A8
|
||||
Light Steel Blue #8F8FBD
|
||||
Light Wood #E9C2A6
|
||||
Lime Green #32CD32
|
||||
Mandarian Orange #E47833
|
||||
Maroon #8E236B
|
||||
Medium Aquamarine #32CD99
|
||||
Medium Blue #3232CD
|
||||
Medium Forest Green #6B8E23
|
||||
Medium Goldenrod #EAEAAE
|
||||
Medium Orchid #9370DB
|
||||
Medium Sea Green #426F42
|
||||
Medium Slate Blue #7F00FF
|
||||
Medium Spring Green #7FFF00
|
||||
Medium Turquoise #70DBDB
|
||||
Medium Violet Red #DB7093
|
||||
Medium Wood #A68064
|
||||
Midnight Blue #2F2F4F
|
||||
Navy Blue #23238E
|
||||
Neon Blue #4D4DFF
|
||||
Neon Pink #FF6EC7
|
||||
New Midnight Blue #00009C
|
||||
New Tan #EBC79E
|
||||
Old Gold #CFB53B
|
||||
Orange #FF7F00
|
||||
Orange Red #FF2400
|
||||
Orchid #DB70DB
|
||||
Pale Green #8FBC8F
|
||||
Pink #BC8F8F
|
||||
Plum #EAADEA
|
||||
Quartz #D9D9F3
|
||||
Rich Blue #5959AB
|
||||
Salmon #6F4242
|
||||
Scarlet #8C1717
|
||||
Sea Green #238E68
|
||||
Semi-Sweet Chocolate #6B4226
|
||||
Sienna #8E6B23
|
||||
Silver #E6E8FA
|
||||
Sky Blue #3299CC
|
||||
Slate Blue #007FFF
|
||||
Spicy Pink #FF1CAE
|
||||
Spring Green #00FF7F
|
||||
Steel Blue #236B8E
|
||||
Summer Sky #38B0DE
|
||||
Tan #DB9370
|
||||
Thistle #D8BFD8
|
||||
Turquoise #ADEAEA
|
||||
Very Dark Brown #5C4033
|
||||
Very Light Grey #CDCDCD
|
||||
Violet #4F2F4F
|
||||
Violet Red #CC3299
|
||||
Wheat #D8D8BF
|
||||
Yellow Green #99CC32
|
125
third_party/python/Tools/pynche/pyColorChooser.py
vendored
Normal file
125
third_party/python/Tools/pynche/pyColorChooser.py
vendored
Normal file
|
@ -0,0 +1,125 @@
|
|||
"""Color chooser implementing (almost) the tkColorColor interface
|
||||
"""
|
||||
|
||||
import os
|
||||
import Main
|
||||
import ColorDB
|
||||
|
||||
|
||||
|
||||
class Chooser:
|
||||
"""Ask for a color"""
|
||||
def __init__(self,
|
||||
master = None,
|
||||
databasefile = None,
|
||||
initfile = None,
|
||||
ignore = None,
|
||||
wantspec = None):
|
||||
self.__master = master
|
||||
self.__databasefile = databasefile
|
||||
self.__initfile = initfile or os.path.expanduser('~/.pynche')
|
||||
self.__ignore = ignore
|
||||
self.__pw = None
|
||||
self.__wantspec = wantspec
|
||||
|
||||
def show(self, color, options):
|
||||
# scan for options that can override the ctor options
|
||||
self.__wantspec = options.get('wantspec', self.__wantspec)
|
||||
dbfile = options.get('databasefile', self.__databasefile)
|
||||
# load the database file
|
||||
colordb = None
|
||||
if dbfile != self.__databasefile:
|
||||
colordb = ColorDB.get_colordb(dbfile)
|
||||
if not self.__master:
|
||||
from tkinter import Tk
|
||||
self.__master = Tk()
|
||||
if not self.__pw:
|
||||
self.__pw, self.__sb = \
|
||||
Main.build(master = self.__master,
|
||||
initfile = self.__initfile,
|
||||
ignore = self.__ignore)
|
||||
else:
|
||||
self.__pw.deiconify()
|
||||
# convert color
|
||||
if colordb:
|
||||
self.__sb.set_colordb(colordb)
|
||||
else:
|
||||
colordb = self.__sb.colordb()
|
||||
if color:
|
||||
r, g, b = Main.initial_color(color, colordb)
|
||||
self.__sb.update_views(r, g, b)
|
||||
# reset the canceled flag and run it
|
||||
self.__sb.canceled(0)
|
||||
Main.run(self.__pw, self.__sb)
|
||||
rgbtuple = self.__sb.current_rgb()
|
||||
self.__pw.withdraw()
|
||||
# check to see if the cancel button was pushed
|
||||
if self.__sb.canceled_p():
|
||||
return None, None
|
||||
# Try to return the color name from the database if there is an exact
|
||||
# match, otherwise use the "#rrggbb" spec. BAW: Forget about color
|
||||
# aliases for now, maybe later we should return these too.
|
||||
name = None
|
||||
if not self.__wantspec:
|
||||
try:
|
||||
name = colordb.find_byrgb(rgbtuple)[0]
|
||||
except ColorDB.BadColor:
|
||||
pass
|
||||
if name is None:
|
||||
name = ColorDB.triplet_to_rrggbb(rgbtuple)
|
||||
return rgbtuple, name
|
||||
|
||||
def save(self):
|
||||
if self.__sb:
|
||||
self.__sb.save_views()
|
||||
|
||||
|
||||
# convenience stuff
|
||||
_chooser = None
|
||||
|
||||
def askcolor(color = None, **options):
|
||||
"""Ask for a color"""
|
||||
global _chooser
|
||||
if not _chooser:
|
||||
_chooser = Chooser(**options)
|
||||
return _chooser.show(color, options)
|
||||
|
||||
def save():
|
||||
global _chooser
|
||||
if _chooser:
|
||||
_chooser.save()
|
||||
|
||||
|
||||
# test stuff
|
||||
if __name__ == '__main__':
|
||||
from tkinter import *
|
||||
|
||||
class Tester:
|
||||
def __init__(self):
|
||||
self.__root = tk = Tk()
|
||||
b = Button(tk, text='Choose Color...', command=self.__choose)
|
||||
b.pack()
|
||||
self.__l = Label(tk)
|
||||
self.__l.pack()
|
||||
q = Button(tk, text='Quit', command=self.__quit)
|
||||
q.pack()
|
||||
|
||||
def __choose(self, event=None):
|
||||
rgb, name = askcolor(master=self.__root)
|
||||
if rgb is None:
|
||||
text = 'You hit CANCEL!'
|
||||
else:
|
||||
r, g, b = rgb
|
||||
text = 'You picked %s (%3d/%3d/%3d)' % (name, r, g, b)
|
||||
self.__l.configure(text=text)
|
||||
|
||||
def __quit(self, event=None):
|
||||
self.__root.quit()
|
||||
|
||||
def run(self):
|
||||
self.__root.mainloop()
|
||||
t = Tester()
|
||||
t.run()
|
||||
# simpler
|
||||
## print 'color:', askcolor()
|
||||
## print 'color:', askcolor()
|
7
third_party/python/Tools/pynche/pynche
vendored
Executable file
7
third_party/python/Tools/pynche/pynche
vendored
Executable file
|
@ -0,0 +1,7 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
"""Run this file under Unix, or when debugging under Windows.
|
||||
Run the file pynche.pyw under Windows to inhibit the console window.
|
||||
"""
|
||||
import Main
|
||||
Main.main()
|
7
third_party/python/Tools/pynche/pynche.pyw
vendored
Executable file
7
third_party/python/Tools/pynche/pynche.pyw
vendored
Executable file
|
@ -0,0 +1,7 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
"""Run this file under Windows to inhibit the console window.
|
||||
Run the file pynche.py under Unix or when debugging under Windows.
|
||||
"""
|
||||
import Main
|
||||
Main.main()
|
141
third_party/python/Tools/pynche/webcolors.txt
vendored
Normal file
141
third_party/python/Tools/pynche/webcolors.txt
vendored
Normal file
|
@ -0,0 +1,141 @@
|
|||
# De-facto NS & MSIE recognized HTML color names
|
||||
AliceBlue #f0f8ff
|
||||
AntiqueWhite #faebd7
|
||||
Aqua #00ffff
|
||||
Aquamarine #7fffd4
|
||||
Azure #f0ffff
|
||||
Beige #f5f5dc
|
||||
Bisque #ffe4c4
|
||||
Black #000000
|
||||
BlanchedAlmond #ffebcd
|
||||
Blue #0000ff
|
||||
BlueViolet #8a2be2
|
||||
Brown #a52a2a
|
||||
BurlyWood #deb887
|
||||
CadetBlue #5f9ea0
|
||||
Chartreuse #7fff00
|
||||
Chocolate #d2691e
|
||||
Coral #ff7f50
|
||||
CornflowerBlue #6495ed
|
||||
Cornsilk #fff8dc
|
||||
Crimson #dc143c
|
||||
Cyan #00ffff
|
||||
DarkBlue #00008b
|
||||
DarkCyan #008b8b
|
||||
DarkGoldenrod #b8860b
|
||||
DarkGray #a9a9a9
|
||||
DarkGreen #006400
|
||||
DarkKhaki #bdb76b
|
||||
DarkMagenta #8b008b
|
||||
DarkOliveGreen #556b2f
|
||||
DarkOrange #ff8c00
|
||||
DarkOrchid #9932cc
|
||||
DarkRed #8b0000
|
||||
DarkSalmon #e9967a
|
||||
DarkSeaGreen #8fbc8f
|
||||
DarkSlateBlue #483d8b
|
||||
DarkSlateGray #2f4f4f
|
||||
DarkTurquoise #00ced1
|
||||
DarkViolet #9400d3
|
||||
DeepPink #ff1493
|
||||
DeepSkyBlue #00bfff
|
||||
DimGray #696969
|
||||
DodgerBlue #1e90ff
|
||||
FireBrick #b22222
|
||||
FloralWhite #fffaf0
|
||||
ForestGreen #228b22
|
||||
Fuchsia #ff00ff
|
||||
Gainsboro #dcdcdc
|
||||
GhostWhite #f8f8ff
|
||||
Gold #ffd700
|
||||
Goldenrod #daa520
|
||||
Gray #808080
|
||||
Green #008000
|
||||
GreenYellow #adff2f
|
||||
Honeydew #f0fff0
|
||||
HotPink #ff69b4
|
||||
IndianRed #cd5c5c
|
||||
Indigo #4b0082
|
||||
Ivory #fffff0
|
||||
Khaki #f0e68c
|
||||
Lavender #e6e6fa
|
||||
LavenderBlush #fff0f5
|
||||
LawnGreen #7cfc00
|
||||
LemonChiffon #fffacd
|
||||
LightBlue #add8e6
|
||||
LightCoral #f08080
|
||||
LightCyan #e0ffff
|
||||
LightGoldenrodYellow #fafad2
|
||||
LightGreen #90ee90
|
||||
LightGrey #d3d3d3
|
||||
LightPink #ffb6c1
|
||||
LightSalmon #ffa07a
|
||||
LightSeaGreen #20b2aa
|
||||
LightSkyBlue #87cefa
|
||||
LightSlateGray #778899
|
||||
LightSteelBlue #b0c4de
|
||||
LightYellow #ffffe0
|
||||
Lime #00ff00
|
||||
LimeGreen #32cd32
|
||||
Linen #faf0e6
|
||||
Magenta #ff00ff
|
||||
Maroon #800000
|
||||
MediumAquamarine #66cdaa
|
||||
MediumBlue #0000cd
|
||||
MediumOrchid #ba55d3
|
||||
MediumPurple #9370db
|
||||
MediumSeaGreen #3cb371
|
||||
MediumSlateBlue #7b68ee
|
||||
MediumSpringGreen #00fa9a
|
||||
MediumTurquoise #48d1cc
|
||||
MediumVioletRed #c71585
|
||||
MidnightBlue #191970
|
||||
MintCream #f5fffa
|
||||
MistyRose #ffe4e1
|
||||
Moccasin #ffe4b5
|
||||
NavajoWhite #ffdead
|
||||
Navy #000080
|
||||
OldLace #fdf5e6
|
||||
Olive #808000
|
||||
OliveDrab #6b8e23
|
||||
Orange #ffa500
|
||||
OrangeRed #ff4500
|
||||
Orchid #da70d6
|
||||
PaleGoldenrod #eee8aa
|
||||
PaleGreen #98fb98
|
||||
PaleTurquoise #afeeee
|
||||
PaleVioletRed #db7093
|
||||
PapayaWhip #ffefd5
|
||||
PeachPuff #ffdab9
|
||||
Peru #cd853f
|
||||
Pink #ffc0cb
|
||||
Plum #dda0dd
|
||||
PowderBlue #b0e0e6
|
||||
Purple #800080
|
||||
Red #ff0000
|
||||
RosyBrown #bc8f8f
|
||||
RoyalBlue #4169e1
|
||||
SaddleBrown #8b4513
|
||||
Salmon #fa8072
|
||||
SandyBrown #f4a460
|
||||
SeaGreen #2e8b57
|
||||
Seashell #fff5ee
|
||||
Sienna #a0522d
|
||||
Silver #c0c0c0
|
||||
SkyBlue #87ceeb
|
||||
SlateBlue #6a5acd
|
||||
SlateGray #708090
|
||||
Snow #fffafa
|
||||
SpringGreen #00ff7f
|
||||
SteelBlue #4682b4
|
||||
Tan #d2b48c
|
||||
Teal #008080
|
||||
Thistle #d8bfd8
|
||||
Tomato #ff6347
|
||||
Turquoise #40e0d0
|
||||
Violet #ee82ee
|
||||
Wheat #f5deb3
|
||||
White #ffffff
|
||||
WhiteSmoke #f5f5f5
|
||||
Yellow #ffff00
|
||||
YellowGreen #9acd32
|
217
third_party/python/Tools/pynche/websafe.txt
vendored
Normal file
217
third_party/python/Tools/pynche/websafe.txt
vendored
Normal file
|
@ -0,0 +1,217 @@
|
|||
# Websafe RGB values
|
||||
#000000
|
||||
#000033
|
||||
#000066
|
||||
#000099
|
||||
#0000cc
|
||||
#0000ff
|
||||
#003300
|
||||
#003333
|
||||
#003366
|
||||
#003399
|
||||
#0033cc
|
||||
#0033ff
|
||||
#006600
|
||||
#006633
|
||||
#006666
|
||||
#006699
|
||||
#0066cc
|
||||
#0066ff
|
||||
#009900
|
||||
#009933
|
||||
#009966
|
||||
#009999
|
||||
#0099cc
|
||||
#0099ff
|
||||
#00cc00
|
||||
#00cc33
|
||||
#00cc66
|
||||
#00cc99
|
||||
#00cccc
|
||||
#00ccff
|
||||
#00ff00
|
||||
#00ff33
|
||||
#00ff66
|
||||
#00ff99
|
||||
#00ffcc
|
||||
#00ffff
|
||||
#330000
|
||||
#330033
|
||||
#330066
|
||||
#330099
|
||||
#3300cc
|
||||
#3300ff
|
||||
#333300
|
||||
#333333
|
||||
#333366
|
||||
#333399
|
||||
#3333cc
|
||||
#3333ff
|
||||
#336600
|
||||
#336633
|
||||
#336666
|
||||
#336699
|
||||
#3366cc
|
||||
#3366ff
|
||||
#339900
|
||||
#339933
|
||||
#339966
|
||||
#339999
|
||||
#3399cc
|
||||
#3399ff
|
||||
#33cc00
|
||||
#33cc33
|
||||
#33cc66
|
||||
#33cc99
|
||||
#33cccc
|
||||
#33ccff
|
||||
#33ff00
|
||||
#33ff33
|
||||
#33ff66
|
||||
#33ff99
|
||||
#33ffcc
|
||||
#33ffff
|
||||
#660000
|
||||
#660033
|
||||
#660066
|
||||
#660099
|
||||
#6600cc
|
||||
#6600ff
|
||||
#663300
|
||||
#663333
|
||||
#663366
|
||||
#663399
|
||||
#6633cc
|
||||
#6633ff
|
||||
#666600
|
||||
#666633
|
||||
#666666
|
||||
#666699
|
||||
#6666cc
|
||||
#6666ff
|
||||
#669900
|
||||
#669933
|
||||
#669966
|
||||
#669999
|
||||
#6699cc
|
||||
#6699ff
|
||||
#66cc00
|
||||
#66cc33
|
||||
#66cc66
|
||||
#66cc99
|
||||
#66cccc
|
||||
#66ccff
|
||||
#66ff00
|
||||
#66ff33
|
||||
#66ff66
|
||||
#66ff99
|
||||
#66ffcc
|
||||
#66ffff
|
||||
#990000
|
||||
#990033
|
||||
#990066
|
||||
#990099
|
||||
#9900cc
|
||||
#9900ff
|
||||
#993300
|
||||
#993333
|
||||
#993366
|
||||
#993399
|
||||
#9933cc
|
||||
#9933ff
|
||||
#996600
|
||||
#996633
|
||||
#996666
|
||||
#996699
|
||||
#9966cc
|
||||
#9966ff
|
||||
#999900
|
||||
#999933
|
||||
#999966
|
||||
#999999
|
||||
#9999cc
|
||||
#9999ff
|
||||
#99cc00
|
||||
#99cc33
|
||||
#99cc66
|
||||
#99cc99
|
||||
#99cccc
|
||||
#99ccff
|
||||
#99ff00
|
||||
#99ff33
|
||||
#99ff66
|
||||
#99ff99
|
||||
#99ffcc
|
||||
#99ffff
|
||||
#cc0000
|
||||
#cc0033
|
||||
#cc0066
|
||||
#cc0099
|
||||
#cc00cc
|
||||
#cc00ff
|
||||
#cc3300
|
||||
#cc3333
|
||||
#cc3366
|
||||
#cc3399
|
||||
#cc33cc
|
||||
#cc33ff
|
||||
#cc6600
|
||||
#cc6633
|
||||
#cc6666
|
||||
#cc6699
|
||||
#cc66cc
|
||||
#cc66ff
|
||||
#cc9900
|
||||
#cc9933
|
||||
#cc9966
|
||||
#cc9999
|
||||
#cc99cc
|
||||
#cc99ff
|
||||
#cccc00
|
||||
#cccc33
|
||||
#cccc66
|
||||
#cccc99
|
||||
#cccccc
|
||||
#ccccff
|
||||
#ccff00
|
||||
#ccff33
|
||||
#ccff66
|
||||
#ccff99
|
||||
#ccffcc
|
||||
#ccffff
|
||||
#ff0000
|
||||
#ff0033
|
||||
#ff0066
|
||||
#ff0099
|
||||
#ff00cc
|
||||
#ff00ff
|
||||
#ff3300
|
||||
#ff3333
|
||||
#ff3366
|
||||
#ff3399
|
||||
#ff33cc
|
||||
#ff33ff
|
||||
#ff6600
|
||||
#ff6633
|
||||
#ff6666
|
||||
#ff6699
|
||||
#ff66cc
|
||||
#ff66ff
|
||||
#ff9900
|
||||
#ff9933
|
||||
#ff9966
|
||||
#ff9999
|
||||
#ff99cc
|
||||
#ff99ff
|
||||
#ffcc00
|
||||
#ffcc33
|
||||
#ffcc66
|
||||
#ffcc99
|
||||
#ffcccc
|
||||
#ffccff
|
||||
#ffff00
|
||||
#ffff33
|
||||
#ffff66
|
||||
#ffff99
|
||||
#ffffcc
|
||||
#ffffff
|
Loading…
Add table
Add a link
Reference in a new issue