blob: 73cbd37f61df615e8502997a1e1fe0b63aa56eef [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 Warsawf67575d1998-03-10 00:17:01 +000010from OptionsWidget import OptionsWidget
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 Warsaw93737b21998-02-17 03:09:19 +0000117 group.pack(side=LEFT, expand=YES, fill=BOTH)
Barry Warsawfefbf791998-01-31 23:39:01 +0000118 self.__selected = ChipWidget(group.interior(),
119 label_text='Selected')
120 self.__selected.grid()
121 self.__nearest = ChipWidget(group.interior(),
122 label_text='Nearest')
123 self.__nearest.grid(row=0, column=1)
Barry Warsaw552ac171998-02-17 22:25:23 +0000124
125 # TBD: this is somewhat bogus, as the code should be in a derived
126 # class of ChipWidget.
127 self.__chip = self.__nearest.component('chip')
128 self.__chip.bind('<ButtonPress-1>', self.__buttonpress)
129 self.__chip.bind('<ButtonRelease-1>', self.__buttonrelease)
Barry Warsawfefbf791998-01-31 23:39:01 +0000130
131 # create the options window
Barry Warsawa6f591a1998-02-11 17:19:54 +0000132 self.__typein = TypeinWidget(group.interior())
Barry Warsaw93737b21998-02-17 03:09:19 +0000133 self.__typein.grid(row=0, column=2)
Barry Warsawfefbf791998-01-31 23:39:01 +0000134
135 # Check keywords and initialize options
136 self.initialiseoptions(PyncheWidget)
137
Barry Warsawa6f591a1998-02-11 17:19:54 +0000138 self.__typein.configure(delegate=self)
Barry Warsaw93737b21998-02-17 03:09:19 +0000139 self.__reds.configure(delegate=self)
140 self.__greens.configure(delegate=self)
141 self.__blues.configure(delegate=self)
Barry Warsawa6f591a1998-02-11 17:19:54 +0000142
143 #
144 # PUBLIC INTERFACE
145 #
146
147
148 def set_color(self, obj, rgbtuple):
Barry Warsawa6f591a1998-02-11 17:19:54 +0000149 nearest = self.__colordb.nearest(rgbtuple)
Barry Warsaw55d3ffa1998-02-11 18:55:50 +0000150 red, green, blue = self.__colordb.find_byname(nearest)
Barry Warsawa6f591a1998-02-11 17:19:54 +0000151 # for an exact match, use the color name
152 if (red, green, blue) == rgbtuple:
153 self.__selected.configure(color=nearest)
154 # otherwise, use the #rrggbb name
155 else:
156 rrggbb = ColorDB.triplet_to_rrggbb(rgbtuple)
157 self.__selected.configure(color=rrggbb)
Barry Warsaw29fe4dd1998-02-12 19:52:31 +0000158
159 # configure all subwidgets
Barry Warsawa6f591a1998-02-11 17:19:54 +0000160 self.__nearest.configure(color=nearest)
161 self.__typein.configure(color=rgbtuple)
Barry Warsaw29fe4dd1998-02-12 19:52:31 +0000162 self.__reds.configure(color=rgbtuple)
163 self.__greens.configure(color=rgbtuple)
164 self.__blues.configure(color=rgbtuple)
Barry Warsawa6f591a1998-02-11 17:19:54 +0000165 delegate = self['delegate']
166 if delegate:
167 delegate.set_color(self, rgbtuple)
168
169 #
170 # PRIVATE INTERFACE
171 #
Barry Warsawfefbf791998-01-31 23:39:01 +0000172
173 def __set_color(self):
Barry Warsawa6f591a1998-02-11 17:19:54 +0000174 self.set_color(self, self['color'])
Barry Warsaw93737b21998-02-17 03:09:19 +0000175
Barry Warsaw552ac171998-02-17 22:25:23 +0000176 def __buttonpress(self, event=None):
177 self.__chip.configure(relief=SUNKEN)
178
179 def __buttonrelease(self, event=None):
180 self.__chip.configure(relief=RAISED)
Barry Warsaw93737b21998-02-17 03:09:19 +0000181 color = self.__nearest['color']
182 rgbtuple = self.__colordb.find_byname(color)
183 self.set_color(self, rgbtuple)
Barry Warsaw552ac171998-02-17 22:25:23 +0000184
185 def __quit(self, event=None):
186 self.__parent.quit()
187
188 def __popup_about(self, event=None):
Barry Warsawf67575d1998-03-10 00:17:01 +0000189 if not self.__about_dialog:
Barry Warsaw552ac171998-02-17 22:25:23 +0000190 Pmw.aboutversion('1.0')
191 Pmw.aboutcopyright('Copyright (C) 1998 Barry A. Warsaw\n'
192 'All rights reserved')
193 Pmw.aboutcontact('For information about Pynche contact:\n'
194 'Barry A. Warsaw\n'
195 'email: bwarsaw@python.org')
Barry Warsawf67575d1998-03-10 00:17:01 +0000196 self.__about_dialog = Pmw.AboutDialog(
Barry Warsaw552ac171998-02-17 22:25:23 +0000197 applicationname='Pynche -- the PYthonically Natural\n'
198 'Color and Hue Editor')
Barry Warsawf67575d1998-03-10 00:17:01 +0000199 self.__about_dialog.show()
200
201 def __popup_options(self, event=None):
202 if not self.__options_dialog:
203 self.__options_dialog = OptionsWidget()
204 self.__options_dialog.activate()
205 # now gather up the new options
206 self.__typein.set_update_on_typing(
207 self.__options_dialog.get_value('typing'))