1998-01-31 19:39:01 -04:00
|
|
|
|
"""Main Pynche (Pythonically Natural Color and Hue Editor) widget.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from Tkinter import *
|
|
|
|
|
import Pmw
|
|
|
|
|
import ColorDB
|
|
|
|
|
from ChipWidget import ChipWidget
|
1998-02-11 13:19:54 -04:00
|
|
|
|
from TypeinWidget import TypeinWidget
|
1998-02-12 15:52:31 -04:00
|
|
|
|
from StripWidget import StripWidget
|
1998-03-16 19:08:35 -04:00
|
|
|
|
from OptionsWidget import PyncheOptions
|
1998-01-31 19:39:01 -04:00
|
|
|
|
|
1998-02-17 18:25:23 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ABOUTTEXT = '''Pynche 1.0 -- The Pythonically Natural Color and Hue Editor
|
|
|
|
|
Copyright (C) 1998 Barry A. Warsaw
|
|
|
|
|
|
|
|
|
|
Pynche is based on ICE 1.2 (Interactive Color Editor), written by
|
|
|
|
|
Barry A. Warsaw for the SunView window system in 1987.'''
|
|
|
|
|
|
|
|
|
|
|
1998-02-12 15:52:31 -04:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
1998-02-13 17:28:14 -04:00
|
|
|
|
# red variations, green+blue = cyan constant
|
|
|
|
|
def constant_cyan_generator(numchips, rgbtuple):
|
|
|
|
|
red, green, blue = rgbtuple
|
1998-02-12 15:52:31 -04:00
|
|
|
|
seq = constant(numchips)
|
1998-02-13 17:28:14 -04:00
|
|
|
|
return map(None, seq, [green] * numchips, [blue] * numchips)
|
1998-02-12 15:52:31 -04:00
|
|
|
|
|
1998-02-13 17:28:14 -04:00
|
|
|
|
# green variations, red+blue = magenta constant
|
|
|
|
|
def constant_magenta_generator(numchips, rgbtuple):
|
|
|
|
|
red, green, blue = rgbtuple
|
1998-02-12 15:52:31 -04:00
|
|
|
|
seq = constant(numchips)
|
1998-02-13 17:28:14 -04:00
|
|
|
|
return map(None, [red] * numchips, seq, [blue] * numchips)
|
1998-02-12 15:52:31 -04:00
|
|
|
|
|
1998-02-13 17:28:14 -04:00
|
|
|
|
# blue variations, red+green = yellow constant
|
|
|
|
|
def constant_yellow_generator(numchips, rgbtuple):
|
|
|
|
|
red, green, blue = rgbtuple
|
1998-02-12 15:52:31 -04:00
|
|
|
|
seq = constant(numchips)
|
1998-02-13 17:28:14 -04:00
|
|
|
|
return map(None, [red] * numchips, [green] * numchips, seq)
|
1998-02-12 15:52:31 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1998-01-31 19:39:01 -04:00
|
|
|
|
class PyncheWidget(Pmw.MegaWidget):
|
|
|
|
|
def __init__(self, colordb, parent=None, **kw):
|
|
|
|
|
self.__colordb = colordb
|
1998-02-17 18:25:23 -04:00
|
|
|
|
self.__parent = parent
|
1998-03-09 20:17:01 -04:00
|
|
|
|
self.__about_dialog = None
|
|
|
|
|
self.__options_dialog = None
|
1998-01-31 19:39:01 -04:00
|
|
|
|
|
1998-02-11 13:19:54 -04:00
|
|
|
|
options = (('color', (128, 128, 128), self.__set_color),
|
|
|
|
|
('delegate', None, None),
|
|
|
|
|
)
|
|
|
|
|
self.defineoptions(kw, options)
|
1998-01-31 19:39:01 -04:00
|
|
|
|
|
|
|
|
|
# initialize base class -- after defining options
|
|
|
|
|
Pmw.MegaWidget.__init__(self, parent)
|
1998-02-17 18:25:23 -04:00
|
|
|
|
|
|
|
|
|
# create menubar
|
|
|
|
|
self.__menubar = Pmw.MenuBar(parent,
|
|
|
|
|
hull_relief=RAISED,
|
|
|
|
|
hull_borderwidth=1)
|
|
|
|
|
self.__menubar.pack(side=TOP, expand=YES, fill=BOTH)
|
|
|
|
|
self.__menubar.addmenu('File', None)
|
|
|
|
|
self.__menubar.addmenuitem('File',
|
|
|
|
|
type=COMMAND,
|
|
|
|
|
label='Quit',
|
|
|
|
|
command=self.__quit,
|
|
|
|
|
accelerator='Alt-Q')
|
1998-03-09 20:17:01 -04:00
|
|
|
|
parent.bind('<Alt-q>', self.__quit)
|
|
|
|
|
parent.bind('<Alt-Q>', self.__quit)
|
|
|
|
|
|
1998-02-17 18:25:23 -04:00
|
|
|
|
self.__menubar.addmenu('Help', None, side=RIGHT)
|
|
|
|
|
self.__menubar.addmenuitem('Help',
|
|
|
|
|
type=COMMAND,
|
|
|
|
|
label='About...',
|
|
|
|
|
command=self.__popup_about,
|
|
|
|
|
accelerator='Alt-A')
|
|
|
|
|
parent.bind('<Alt-a>', self.__popup_about)
|
|
|
|
|
parent.bind('<Alt-A>', self.__popup_about)
|
1998-01-31 19:39:01 -04:00
|
|
|
|
|
1998-03-09 20:17:01 -04:00
|
|
|
|
self.__menubar.addmenu('Edit', None)
|
|
|
|
|
self.__menubar.addmenuitem('Edit',
|
|
|
|
|
type=COMMAND,
|
|
|
|
|
label='Options...',
|
|
|
|
|
command=self.__popup_options,
|
|
|
|
|
accelerator='Alt-O')
|
|
|
|
|
parent.bind('<Alt-o>', self.__popup_options)
|
|
|
|
|
parent.bind('<Alt-O>', self.__popup_options)
|
|
|
|
|
|
1998-01-31 19:39:01 -04:00
|
|
|
|
# create color selectors
|
1998-02-16 23:09:19 -04:00
|
|
|
|
group = Pmw.Group(parent, tag_text='Variations')
|
1998-02-12 15:52:31 -04:00
|
|
|
|
group.pack(side=TOP, expand=YES, fill=BOTH)
|
|
|
|
|
self.__reds = StripWidget(group.interior(),
|
1998-02-13 17:28:14 -04:00
|
|
|
|
generator=constant_cyan_generator,
|
1998-02-16 23:09:19 -04:00
|
|
|
|
axis=0, label='Red Variations')
|
1998-02-12 15:52:31 -04:00
|
|
|
|
self.__reds.pack()
|
|
|
|
|
self.__blues = StripWidget(group.interior(),
|
1998-02-13 17:28:14 -04:00
|
|
|
|
generator=constant_magenta_generator,
|
1998-02-16 23:09:19 -04:00
|
|
|
|
axis=1, label='Green Variations')
|
1998-02-12 15:52:31 -04:00
|
|
|
|
self.__blues.pack()
|
|
|
|
|
self.__greens = StripWidget(group.interior(),
|
1998-02-13 17:28:14 -04:00
|
|
|
|
generator=constant_yellow_generator,
|
1998-02-16 23:09:19 -04:00
|
|
|
|
axis=2, label='Blue Variations')
|
1998-02-12 15:52:31 -04:00
|
|
|
|
self.__greens.pack()
|
1998-01-31 19:39:01 -04:00
|
|
|
|
|
|
|
|
|
# create chip window
|
|
|
|
|
group = Pmw.Group(parent, tag_text='Current Color')
|
1998-03-16 19:08:35 -04:00
|
|
|
|
interior = group.interior()
|
1998-02-16 23:09:19 -04:00
|
|
|
|
group.pack(side=LEFT, expand=YES, fill=BOTH)
|
1998-03-16 19:08:35 -04:00
|
|
|
|
self.__selected = ChipWidget(interior,
|
1998-01-31 19:39:01 -04:00
|
|
|
|
label_text='Selected')
|
|
|
|
|
self.__selected.grid()
|
1998-03-16 19:08:35 -04:00
|
|
|
|
self.__nearest = ChipWidget(interior,
|
1998-01-31 19:39:01 -04:00
|
|
|
|
label_text='Nearest')
|
|
|
|
|
self.__nearest.grid(row=0, column=1)
|
1998-02-17 18:25:23 -04:00
|
|
|
|
|
|
|
|
|
# TBD: this is somewhat bogus, as the code should be in a derived
|
|
|
|
|
# class of ChipWidget.
|
|
|
|
|
self.__chip = self.__nearest.component('chip')
|
|
|
|
|
self.__chip.bind('<ButtonPress-1>', self.__buttonpress)
|
|
|
|
|
self.__chip.bind('<ButtonRelease-1>', self.__buttonrelease)
|
1998-01-31 19:39:01 -04:00
|
|
|
|
|
1998-03-16 19:08:35 -04:00
|
|
|
|
# create the type-in window
|
|
|
|
|
self.__typein = TypeinWidget(interior)
|
1998-02-16 23:09:19 -04:00
|
|
|
|
self.__typein.grid(row=0, column=2)
|
1998-01-31 19:39:01 -04:00
|
|
|
|
|
|
|
|
|
# Check keywords and initialize options
|
|
|
|
|
self.initialiseoptions(PyncheWidget)
|
|
|
|
|
|
1998-02-11 13:19:54 -04:00
|
|
|
|
self.__typein.configure(delegate=self)
|
1998-02-16 23:09:19 -04:00
|
|
|
|
self.__reds.configure(delegate=self)
|
|
|
|
|
self.__greens.configure(delegate=self)
|
|
|
|
|
self.__blues.configure(delegate=self)
|
1998-01-31 19:39:01 -04:00
|
|
|
|
|
1998-02-11 13:19:54 -04:00
|
|
|
|
#
|
|
|
|
|
# PUBLIC INTERFACE
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def set_color(self, obj, rgbtuple):
|
|
|
|
|
nearest = self.__colordb.nearest(rgbtuple)
|
1998-02-11 14:55:50 -04:00
|
|
|
|
red, green, blue = self.__colordb.find_byname(nearest)
|
1998-02-11 13:19:54 -04:00
|
|
|
|
# for an exact match, use the color name
|
|
|
|
|
if (red, green, blue) == rgbtuple:
|
|
|
|
|
self.__selected.configure(color=nearest)
|
|
|
|
|
# otherwise, use the #rrggbb name
|
|
|
|
|
else:
|
|
|
|
|
rrggbb = ColorDB.triplet_to_rrggbb(rgbtuple)
|
|
|
|
|
self.__selected.configure(color=rrggbb)
|
1998-02-12 15:52:31 -04:00
|
|
|
|
|
|
|
|
|
# configure all subwidgets
|
1998-01-31 19:39:01 -04:00
|
|
|
|
self.__nearest.configure(color=nearest)
|
1998-02-11 13:19:54 -04:00
|
|
|
|
self.__typein.configure(color=rgbtuple)
|
1998-02-12 15:52:31 -04:00
|
|
|
|
self.__reds.configure(color=rgbtuple)
|
|
|
|
|
self.__greens.configure(color=rgbtuple)
|
|
|
|
|
self.__blues.configure(color=rgbtuple)
|
1998-02-11 13:19:54 -04:00
|
|
|
|
delegate = self['delegate']
|
|
|
|
|
if delegate:
|
|
|
|
|
delegate.set_color(self, rgbtuple)
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# PRIVATE INTERFACE
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
def __set_color(self):
|
|
|
|
|
self.set_color(self, self['color'])
|
1998-02-16 23:09:19 -04:00
|
|
|
|
|
1998-02-17 18:25:23 -04:00
|
|
|
|
def __buttonpress(self, event=None):
|
|
|
|
|
self.__chip.configure(relief=SUNKEN)
|
|
|
|
|
|
|
|
|
|
def __buttonrelease(self, event=None):
|
|
|
|
|
self.__chip.configure(relief=RAISED)
|
1998-02-16 23:09:19 -04:00
|
|
|
|
color = self.__nearest['color']
|
|
|
|
|
rgbtuple = self.__colordb.find_byname(color)
|
|
|
|
|
self.set_color(self, rgbtuple)
|
1998-02-17 18:25:23 -04:00
|
|
|
|
|
|
|
|
|
def __quit(self, event=None):
|
|
|
|
|
self.__parent.quit()
|
|
|
|
|
|
|
|
|
|
def __popup_about(self, event=None):
|
1998-03-09 20:17:01 -04:00
|
|
|
|
if not self.__about_dialog:
|
1998-02-17 18:25:23 -04:00
|
|
|
|
Pmw.aboutversion('1.0')
|
|
|
|
|
Pmw.aboutcopyright('Copyright (C) 1998 Barry A. Warsaw\n'
|
|
|
|
|
'All rights reserved')
|
|
|
|
|
Pmw.aboutcontact('For information about Pynche contact:\n'
|
|
|
|
|
'Barry A. Warsaw\n'
|
|
|
|
|
'email: bwarsaw@python.org')
|
1998-03-09 20:17:01 -04:00
|
|
|
|
self.__about_dialog = Pmw.AboutDialog(
|
1998-02-17 18:25:23 -04:00
|
|
|
|
applicationname='Pynche -- the PYthonically Natural\n'
|
|
|
|
|
'Color and Hue Editor')
|
1998-03-09 20:17:01 -04:00
|
|
|
|
self.__about_dialog.show()
|
|
|
|
|
|
|
|
|
|
def __popup_options(self, event=None):
|
|
|
|
|
if not self.__options_dialog:
|
1998-03-16 19:08:35 -04:00
|
|
|
|
self.__options_dialog = PyncheOptions(
|
|
|
|
|
title='Pynche Options',
|
|
|
|
|
applycommand=self.__apply)
|
|
|
|
|
# pop up the window, non-modal
|
|
|
|
|
self.__options_dialog.deiconify()
|
|
|
|
|
|
|
|
|
|
def __apply(self):
|
1998-03-09 20:17:01 -04:00
|
|
|
|
self.__typein.set_update_on_typing(
|
|
|
|
|
self.__options_dialog.get_value('typing'))
|
1998-03-16 19:08:35 -04:00
|
|
|
|
flag = self.__options_dialog.get_value('dragging')
|
|
|
|
|
for strip in (self.__reds, self.__greens, self.__blues):
|
|
|
|
|
strip.set_update_while_dragging(flag)
|