blob: a16cbcdb0505ad1ff7f936d33f83887e7ba33e9a [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 Warsawa114eb51998-03-16 23:08:35 +000010from OptionsWidget import PyncheOptions
Barry Warsawfefbf791998-01-31 23:39:01 +000011
Barry Warsaw552ac171998-02-17 22:25:23 +000012
13
14ABOUTTEXT = '''Pynche 1.0 -- The Pythonically Natural Color and Hue Editor
15Copyright (C) 1998 Barry A. Warsaw
16
17Pynche is based on ICE 1.2 (Interactive Color Editor), written by
18Barry A. Warsaw for the SunView window system in 1987.'''
19
20
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000021
22def constant(numchips):
23 step = 255.0 / (numchips - 1)
24 start = 0.0
25 seq = []
26 while numchips > 0:
27 seq.append(int(start))
28 start = start + step
29 numchips = numchips - 1
30 return seq
31
Barry Warsaw79a78791998-02-13 21:28:14 +000032# red variations, green+blue = cyan constant
33def constant_cyan_generator(numchips, rgbtuple):
34 red, green, blue = rgbtuple
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000035 seq = constant(numchips)
Barry Warsaw79a78791998-02-13 21:28:14 +000036 return map(None, seq, [green] * numchips, [blue] * numchips)
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000037
Barry Warsaw79a78791998-02-13 21:28:14 +000038# green variations, red+blue = magenta constant
39def constant_magenta_generator(numchips, rgbtuple):
40 red, green, blue = rgbtuple
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000041 seq = constant(numchips)
Barry Warsaw79a78791998-02-13 21:28:14 +000042 return map(None, [red] * numchips, seq, [blue] * numchips)
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000043
Barry Warsaw79a78791998-02-13 21:28:14 +000044# blue variations, red+green = yellow constant
45def constant_yellow_generator(numchips, rgbtuple):
46 red, green, blue = rgbtuple
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000047 seq = constant(numchips)
Barry Warsaw79a78791998-02-13 21:28:14 +000048 return map(None, [red] * numchips, [green] * numchips, seq)
Barry Warsaw29fe4dd1998-02-12 19:52:31 +000049
50
51
Barry Warsawfefbf791998-01-31 23:39:01 +000052class PyncheWidget(Pmw.MegaWidget):
53 def __init__(self, colordb, parent=None, **kw):
54 self.__colordb = colordb
Barry Warsaw552ac171998-02-17 22:25:23 +000055 self.__parent = parent
Barry Warsawf67575d1998-03-10 00:17:01 +000056 self.__about_dialog = None
57 self.__options_dialog = None
Barry Warsawfefbf791998-01-31 23:39:01 +000058
Barry Warsawa6f591a1998-02-11 17:19:54 +000059 options = (('color', (128, 128, 128), self.__set_color),
60 ('delegate', None, None),
61 )
62 self.defineoptions(kw, options)
Barry Warsawfefbf791998-01-31 23:39:01 +000063
64 # initialize base class -- after defining options
65 Pmw.MegaWidget.__init__(self, parent)
Barry Warsaw552ac171998-02-17 22:25:23 +000066
67 # create menubar
68 self.__menubar = Pmw.MenuBar(parent,
69 hull_relief=RAISED,
70 hull_borderwidth=1)
71 self.__menubar.pack(side=TOP, expand=YES, fill=BOTH)
72 self.__menubar.addmenu('File', None)
73 self.__menubar.addmenuitem('File',
74 type=COMMAND,
75 label='Quit',
76 command=self.__quit,
77 accelerator='Alt-Q')
Barry Warsawf67575d1998-03-10 00:17:01 +000078 parent.bind('<Alt-q>', self.__quit)
79 parent.bind('<Alt-Q>', self.__quit)
80
Barry Warsaw552ac171998-02-17 22:25:23 +000081 self.__menubar.addmenu('Help', None, side=RIGHT)
82 self.__menubar.addmenuitem('Help',
83 type=COMMAND,
84 label='About...',
85 command=self.__popup_about,
86 accelerator='Alt-A')
Barry Warsaw552ac171998-02-17 22:25:23 +000087 parent.bind('<Alt-a>', self.__popup_about)
88 parent.bind('<Alt-A>', self.__popup_about)
Barry Warsawfefbf791998-01-31 23:39:01 +000089
Barry Warsawf67575d1998-03-10 00:17:01 +000090 self.__menubar.addmenu('Edit', None)
91 self.__menubar.addmenuitem('Edit',
92 type=COMMAND,
93 label='Options...',
94 command=self.__popup_options,
95 accelerator='Alt-O')
96 parent.bind('<Alt-o>', self.__popup_options)
97 parent.bind('<Alt-O>', self.__popup_options)
98
Barry Warsawfefbf791998-01-31 23:39:01 +000099 # create color selectors
Barry Warsaw93737b21998-02-17 03:09:19 +0000100 group = Pmw.Group(parent, tag_text='Variations')
Barry Warsaw29fe4dd1998-02-12 19:52:31 +0000101 group.pack(side=TOP, expand=YES, fill=BOTH)
102 self.__reds = StripWidget(group.interior(),
Barry Warsaw79a78791998-02-13 21:28:14 +0000103 generator=constant_cyan_generator,
Barry Warsaw93737b21998-02-17 03:09:19 +0000104 axis=0, label='Red Variations')
Barry Warsaw29fe4dd1998-02-12 19:52:31 +0000105 self.__reds.pack()
106 self.__blues = StripWidget(group.interior(),
Barry Warsaw79a78791998-02-13 21:28:14 +0000107 generator=constant_magenta_generator,
Barry Warsaw93737b21998-02-17 03:09:19 +0000108 axis=1, label='Green Variations')
Barry Warsaw29fe4dd1998-02-12 19:52:31 +0000109 self.__blues.pack()
110 self.__greens = StripWidget(group.interior(),
Barry Warsaw79a78791998-02-13 21:28:14 +0000111 generator=constant_yellow_generator,
Barry Warsaw93737b21998-02-17 03:09:19 +0000112 axis=2, label='Blue Variations')
Barry Warsaw29fe4dd1998-02-12 19:52:31 +0000113 self.__greens.pack()
Barry Warsawfefbf791998-01-31 23:39:01 +0000114
115 # create chip window
116 group = Pmw.Group(parent, tag_text='Current Color')
Barry Warsawa114eb51998-03-16 23:08:35 +0000117 interior = group.interior()
Barry Warsaw93737b21998-02-17 03:09:19 +0000118 group.pack(side=LEFT, expand=YES, fill=BOTH)
Barry Warsawa114eb51998-03-16 23:08:35 +0000119 self.__selected = ChipWidget(interior,
Barry Warsawfefbf791998-01-31 23:39:01 +0000120 label_text='Selected')
121 self.__selected.grid()
Barry Warsawa114eb51998-03-16 23:08:35 +0000122 self.__nearest = ChipWidget(interior,
Barry Warsawfefbf791998-01-31 23:39:01 +0000123 label_text='Nearest')
124 self.__nearest.grid(row=0, column=1)
Barry Warsaw552ac171998-02-17 22:25:23 +0000125
126 # TBD: this is somewhat bogus, as the code should be in a derived
127 # class of ChipWidget.
128 self.__chip = self.__nearest.component('chip')
129 self.__chip.bind('<ButtonPress-1>', self.__buttonpress)
130 self.__chip.bind('<ButtonRelease-1>', self.__buttonrelease)
Barry Warsawfefbf791998-01-31 23:39:01 +0000131
Barry Warsawa114eb51998-03-16 23:08:35 +0000132 # create the type-in window
133 self.__typein = TypeinWidget(interior)
Barry Warsaw93737b21998-02-17 03:09:19 +0000134 self.__typein.grid(row=0, column=2)
Barry Warsawfefbf791998-01-31 23:39:01 +0000135
136 # Check keywords and initialize options
137 self.initialiseoptions(PyncheWidget)
138
Barry Warsawa6f591a1998-02-11 17:19:54 +0000139 self.__typein.configure(delegate=self)
Barry Warsaw93737b21998-02-17 03:09:19 +0000140 self.__reds.configure(delegate=self)
141 self.__greens.configure(delegate=self)
142 self.__blues.configure(delegate=self)
Barry Warsawa6f591a1998-02-11 17:19:54 +0000143
144 #
145 # PUBLIC INTERFACE
146 #
147
148
149 def set_color(self, obj, rgbtuple):
Barry Warsawa6f591a1998-02-11 17:19:54 +0000150 nearest = self.__colordb.nearest(rgbtuple)
Barry Warsaw55d3ffa1998-02-11 18:55:50 +0000151 red, green, blue = self.__colordb.find_byname(nearest)
Barry Warsawa6f591a1998-02-11 17:19:54 +0000152 # for an exact match, use the color name
153 if (red, green, blue) == rgbtuple:
154 self.__selected.configure(color=nearest)
155 # otherwise, use the #rrggbb name
156 else:
157 rrggbb = ColorDB.triplet_to_rrggbb(rgbtuple)
158 self.__selected.configure(color=rrggbb)
Barry Warsaw29fe4dd1998-02-12 19:52:31 +0000159
160 # configure all subwidgets
Barry Warsawa6f591a1998-02-11 17:19:54 +0000161 self.__nearest.configure(color=nearest)
162 self.__typein.configure(color=rgbtuple)
Barry Warsaw29fe4dd1998-02-12 19:52:31 +0000163 self.__reds.configure(color=rgbtuple)
164 self.__greens.configure(color=rgbtuple)
165 self.__blues.configure(color=rgbtuple)
Barry Warsawa6f591a1998-02-11 17:19:54 +0000166 delegate = self['delegate']
167 if delegate:
168 delegate.set_color(self, rgbtuple)
169
170 #
171 # PRIVATE INTERFACE
172 #
Barry Warsawfefbf791998-01-31 23:39:01 +0000173
174 def __set_color(self):
Barry Warsawa6f591a1998-02-11 17:19:54 +0000175 self.set_color(self, self['color'])
Barry Warsaw93737b21998-02-17 03:09:19 +0000176
Barry Warsaw552ac171998-02-17 22:25:23 +0000177 def __buttonpress(self, event=None):
178 self.__chip.configure(relief=SUNKEN)
179
180 def __buttonrelease(self, event=None):
181 self.__chip.configure(relief=RAISED)
Barry Warsaw93737b21998-02-17 03:09:19 +0000182 color = self.__nearest['color']
183 rgbtuple = self.__colordb.find_byname(color)
184 self.set_color(self, rgbtuple)
Barry Warsaw552ac171998-02-17 22:25:23 +0000185
186 def __quit(self, event=None):
187 self.__parent.quit()
188
189 def __popup_about(self, event=None):
Barry Warsawf67575d1998-03-10 00:17:01 +0000190 if not self.__about_dialog:
Barry Warsaw552ac171998-02-17 22:25:23 +0000191 Pmw.aboutversion('1.0')
192 Pmw.aboutcopyright('Copyright (C) 1998 Barry A. Warsaw\n'
193 'All rights reserved')
194 Pmw.aboutcontact('For information about Pynche contact:\n'
195 'Barry A. Warsaw\n'
196 'email: bwarsaw@python.org')
Barry Warsawf67575d1998-03-10 00:17:01 +0000197 self.__about_dialog = Pmw.AboutDialog(
Barry Warsaw552ac171998-02-17 22:25:23 +0000198 applicationname='Pynche -- the PYthonically Natural\n'
199 'Color and Hue Editor')
Barry Warsawf67575d1998-03-10 00:17:01 +0000200 self.__about_dialog.show()
201
202 def __popup_options(self, event=None):
203 if not self.__options_dialog:
Barry Warsawa114eb51998-03-16 23:08:35 +0000204 self.__options_dialog = PyncheOptions(
205 title='Pynche Options',
206 applycommand=self.__apply)
207 # pop up the window, non-modal
208 self.__options_dialog.deiconify()
209
210 def __apply(self):
Barry Warsawf67575d1998-03-10 00:17:01 +0000211 self.__typein.set_update_on_typing(
212 self.__options_dialog.get_value('typing'))
Barry Warsawa114eb51998-03-16 23:08:35 +0000213 flag = self.__options_dialog.get_value('dragging')
214 for strip in (self.__reds, self.__greens, self.__blues):
215 strip.set_update_while_dragging(flag)