blob: f2667554affd9d16fd56cadd522703770d2c4df7 [file] [log] [blame]
Barry Warsawfefbf791998-01-31 23:39:01 +00001"""Main Pynche (Pythonically Natural Color and Hue Editor) widget.
2"""
3
4from Tkinter import *
5import Pmw
6import ColorDB
7from ChipWidget import ChipWidget
Barry Warsawa6f591a1998-02-11 17:19:54 +00008from TypeinWidget import TypeinWidget
Barry Warsaw29fe4dd1998-02-12 19:52:31 +00009from StripWidget import StripWidget
Barry Warsawfefbf791998-01-31 23:39:01 +000010
Barry Warsaw552ac171998-02-17 22:25:23 +000011
12
13ABOUTTEXT = '''Pynche 1.0 -- The Pythonically Natural Color and Hue Editor
14Copyright (C) 1998 Barry A. Warsaw
15
16Pynche is based on ICE 1.2 (Interactive Color Editor), written by
17Barry A. Warsaw for the SunView window system in 1987.'''
18
19
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000020
21def constant(numchips):
22 step = 255.0 / (numchips - 1)
23 start = 0.0
24 seq = []
25 while numchips > 0:
26 seq.append(int(start))
27 start = start + step
28 numchips = numchips - 1
29 return seq
30
Barry Warsaw79a78791998-02-13 21:28:14 +000031# red variations, green+blue = cyan constant
32def constant_cyan_generator(numchips, rgbtuple):
33 red, green, blue = rgbtuple
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000034 seq = constant(numchips)
Barry Warsaw79a78791998-02-13 21:28:14 +000035 return map(None, seq, [green] * numchips, [blue] * numchips)
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000036
Barry Warsaw79a78791998-02-13 21:28:14 +000037# green variations, red+blue = magenta constant
38def constant_magenta_generator(numchips, rgbtuple):
39 red, green, blue = rgbtuple
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000040 seq = constant(numchips)
Barry Warsaw79a78791998-02-13 21:28:14 +000041 return map(None, [red] * numchips, seq, [blue] * numchips)
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000042
Barry Warsaw79a78791998-02-13 21:28:14 +000043# blue variations, red+green = yellow constant
44def constant_yellow_generator(numchips, rgbtuple):
45 red, green, blue = rgbtuple
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000046 seq = constant(numchips)
Barry Warsaw79a78791998-02-13 21:28:14 +000047 return map(None, [red] * numchips, [green] * numchips, seq)
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000048
49
50
Barry Warsawfefbf791998-01-31 23:39:01 +000051class PyncheWidget(Pmw.MegaWidget):
52 def __init__(self, colordb, parent=None, **kw):
53 self.__colordb = colordb
Barry Warsaw552ac171998-02-17 22:25:23 +000054 self.__parent = parent
55 self.__about = None
Barry Warsawfefbf791998-01-31 23:39:01 +000056
Barry Warsawa6f591a1998-02-11 17:19:54 +000057 options = (('color', (128, 128, 128), self.__set_color),
58 ('delegate', None, None),
59 )
60 self.defineoptions(kw, options)
Barry Warsawfefbf791998-01-31 23:39:01 +000061
62 # initialize base class -- after defining options
63 Pmw.MegaWidget.__init__(self, parent)
Barry Warsaw552ac171998-02-17 22:25:23 +000064
65 # create menubar
66 self.__menubar = Pmw.MenuBar(parent,
67 hull_relief=RAISED,
68 hull_borderwidth=1)
69 self.__menubar.pack(side=TOP, expand=YES, fill=BOTH)
70 self.__menubar.addmenu('File', None)
71 self.__menubar.addmenuitem('File',
72 type=COMMAND,
73 label='Quit',
74 command=self.__quit,
75 accelerator='Alt-Q')
76 self.__menubar.addmenu('Help', None, side=RIGHT)
77 self.__menubar.addmenuitem('Help',
78 type=COMMAND,
79 label='About...',
80 command=self.__popup_about,
81 accelerator='Alt-A')
82 parent.bind('<Alt-q>', self.__quit)
83 parent.bind('<Alt-Q>', self.__quit)
84 parent.bind('<Alt-a>', self.__popup_about)
85 parent.bind('<Alt-A>', self.__popup_about)
Barry Warsawfefbf791998-01-31 23:39:01 +000086
87 # create color selectors
Barry Warsaw93737b21998-02-17 03:09:19 +000088 group = Pmw.Group(parent, tag_text='Variations')
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000089 group.pack(side=TOP, expand=YES, fill=BOTH)
90 self.__reds = StripWidget(group.interior(),
Barry Warsaw79a78791998-02-13 21:28:14 +000091 generator=constant_cyan_generator,
Barry Warsaw93737b21998-02-17 03:09:19 +000092 axis=0, label='Red Variations')
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000093 self.__reds.pack()
94 self.__blues = StripWidget(group.interior(),
Barry Warsaw79a78791998-02-13 21:28:14 +000095 generator=constant_magenta_generator,
Barry Warsaw93737b21998-02-17 03:09:19 +000096 axis=1, label='Green Variations')
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000097 self.__blues.pack()
98 self.__greens = StripWidget(group.interior(),
Barry Warsaw79a78791998-02-13 21:28:14 +000099 generator=constant_yellow_generator,
Barry Warsaw93737b21998-02-17 03:09:19 +0000100 axis=2, label='Blue Variations')
Barry Warsaw29fe4dd1998-02-12 19:52:31 +0000101 self.__greens.pack()
Barry Warsawfefbf791998-01-31 23:39:01 +0000102
103 # create chip window
104 group = Pmw.Group(parent, tag_text='Current Color')
Barry Warsaw93737b21998-02-17 03:09:19 +0000105 group.pack(side=LEFT, expand=YES, fill=BOTH)
Barry Warsawfefbf791998-01-31 23:39:01 +0000106 self.__selected = ChipWidget(group.interior(),
107 label_text='Selected')
108 self.__selected.grid()
109 self.__nearest = ChipWidget(group.interior(),
110 label_text='Nearest')
111 self.__nearest.grid(row=0, column=1)
Barry Warsaw552ac171998-02-17 22:25:23 +0000112
113 # TBD: this is somewhat bogus, as the code should be in a derived
114 # class of ChipWidget.
115 self.__chip = self.__nearest.component('chip')
116 self.__chip.bind('<ButtonPress-1>', self.__buttonpress)
117 self.__chip.bind('<ButtonRelease-1>', self.__buttonrelease)
Barry Warsawfefbf791998-01-31 23:39:01 +0000118
119 # create the options window
Barry Warsawa6f591a1998-02-11 17:19:54 +0000120 self.__typein = TypeinWidget(group.interior())
Barry Warsaw93737b21998-02-17 03:09:19 +0000121 self.__typein.grid(row=0, column=2)
Barry Warsawfefbf791998-01-31 23:39:01 +0000122
123 # Check keywords and initialize options
124 self.initialiseoptions(PyncheWidget)
125
Barry Warsawa6f591a1998-02-11 17:19:54 +0000126 self.__typein.configure(delegate=self)
Barry Warsaw93737b21998-02-17 03:09:19 +0000127 self.__reds.configure(delegate=self)
128 self.__greens.configure(delegate=self)
129 self.__blues.configure(delegate=self)
Barry Warsawa6f591a1998-02-11 17:19:54 +0000130
131 #
132 # PUBLIC INTERFACE
133 #
134
135
136 def set_color(self, obj, rgbtuple):
Barry Warsawa6f591a1998-02-11 17:19:54 +0000137 nearest = self.__colordb.nearest(rgbtuple)
Barry Warsaw55d3ffa1998-02-11 18:55:50 +0000138 red, green, blue = self.__colordb.find_byname(nearest)
Barry Warsawa6f591a1998-02-11 17:19:54 +0000139 # for an exact match, use the color name
140 if (red, green, blue) == rgbtuple:
141 self.__selected.configure(color=nearest)
142 # otherwise, use the #rrggbb name
143 else:
144 rrggbb = ColorDB.triplet_to_rrggbb(rgbtuple)
145 self.__selected.configure(color=rrggbb)
Barry Warsaw29fe4dd1998-02-12 19:52:31 +0000146
147 # configure all subwidgets
Barry Warsawa6f591a1998-02-11 17:19:54 +0000148 self.__nearest.configure(color=nearest)
149 self.__typein.configure(color=rgbtuple)
Barry Warsaw29fe4dd1998-02-12 19:52:31 +0000150 self.__reds.configure(color=rgbtuple)
151 self.__greens.configure(color=rgbtuple)
152 self.__blues.configure(color=rgbtuple)
Barry Warsawa6f591a1998-02-11 17:19:54 +0000153 delegate = self['delegate']
154 if delegate:
155 delegate.set_color(self, rgbtuple)
156
157 #
158 # PRIVATE INTERFACE
159 #
Barry Warsawfefbf791998-01-31 23:39:01 +0000160
161 def __set_color(self):
Barry Warsawa6f591a1998-02-11 17:19:54 +0000162 self.set_color(self, self['color'])
Barry Warsaw93737b21998-02-17 03:09:19 +0000163
Barry Warsaw552ac171998-02-17 22:25:23 +0000164 def __buttonpress(self, event=None):
165 self.__chip.configure(relief=SUNKEN)
166
167 def __buttonrelease(self, event=None):
168 self.__chip.configure(relief=RAISED)
Barry Warsaw93737b21998-02-17 03:09:19 +0000169 color = self.__nearest['color']
170 rgbtuple = self.__colordb.find_byname(color)
171 self.set_color(self, rgbtuple)
Barry Warsaw552ac171998-02-17 22:25:23 +0000172
173 def __quit(self, event=None):
174 self.__parent.quit()
175
176 def __popup_about(self, event=None):
177 if not self.__about:
178 Pmw.aboutversion('1.0')
179 Pmw.aboutcopyright('Copyright (C) 1998 Barry A. Warsaw\n'
180 'All rights reserved')
181 Pmw.aboutcontact('For information about Pynche contact:\n'
182 'Barry A. Warsaw\n'
183 'email: bwarsaw@python.org')
184 self.__about = Pmw.AboutDialog(
185 applicationname='Pynche -- the PYthonically Natural\n'
186 'Color and Hue Editor')
187 self.__about.show()