summaryrefslogtreecommitdiffstats
path: root/Tools/pynche/PyncheWidget.py
blob: a16cbcdb0505ad1ff7f936d33f83887e7ba33e9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
"""Main Pynche (Pythonically Natural Color and Hue Editor) widget.
"""

from Tkinter import *
import Pmw
import ColorDB
from ChipWidget import ChipWidget
from TypeinWidget import TypeinWidget
from StripWidget import StripWidget
from OptionsWidget import PyncheOptions



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.'''



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_cyan_generator(numchips, rgbtuple):
    red, green, blue = rgbtuple
    seq = constant(numchips)
    return map(None, seq, [green] * numchips, [blue] * numchips)

# green variations, red+blue = magenta constant
def constant_magenta_generator(numchips, rgbtuple):
    red, green, blue = rgbtuple
    seq = constant(numchips)
    return map(None, [red] * numchips, seq, [blue] * numchips)

# blue variations, red+green = yellow constant
def constant_yellow_generator(numchips, rgbtuple):
    red, green, blue = rgbtuple
    seq = constant(numchips)
    return map(None, [red] * numchips, [green] * numchips, seq)



class PyncheWidget(Pmw.MegaWidget):
    def __init__(self, colordb, parent=None, **kw):
	self.__colordb = colordb
	self.__parent = parent
	self.__about_dialog = None
	self.__options_dialog = None

	options = (('color', (128, 128, 128), self.__set_color),
		   ('delegate', None, None),
		   )
	self.defineoptions(kw, options)

	# initialize base class -- after defining options
	Pmw.MegaWidget.__init__(self, parent)

	# 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')
	parent.bind('<Alt-q>', self.__quit)
	parent.bind('<Alt-Q>', self.__quit)

	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)

	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)

	# create color selectors
	group = Pmw.Group(parent, tag_text='Variations')
	group.pack(side=TOP, expand=YES, fill=BOTH)
	self.__reds = StripWidget(group.interior(),
				  generator=constant_cyan_generator,
				  axis=0, label='Red Variations')
	self.__reds.pack()
	self.__blues = StripWidget(group.interior(),
				   generator=constant_magenta_generator,
				   axis=1, label='Green Variations')
	self.__blues.pack()
	self.__greens = StripWidget(group.interior(),
				    generator=constant_yellow_generator,
				    axis=2, label='Blue Variations')
	self.__greens.pack()

	# create chip window
	group = Pmw.Group(parent, tag_text='Current Color')
        interior = group.interior()
	group.pack(side=LEFT, expand=YES, fill=BOTH)
	self.__selected = ChipWidget(interior,
				     label_text='Selected')
	self.__selected.grid()
	self.__nearest = ChipWidget(interior,
				    label_text='Nearest')
	self.__nearest.grid(row=0, column=1)

	# 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)

	# create the type-in window
	self.__typein = TypeinWidget(interior)
	self.__typein.grid(row=0, column=2)

	# Check keywords and initialize options
	self.initialiseoptions(PyncheWidget)

	self.__typein.configure(delegate=self)
	self.__reds.configure(delegate=self)
	self.__greens.configure(delegate=self)
	self.__blues.configure(delegate=self)

    #
    # PUBLIC INTERFACE
    #


    def set_color(self, obj, rgbtuple):
	nearest = self.__colordb.nearest(rgbtuple)
	red, green, blue = self.__colordb.find_byname(nearest)
	# 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)

	# configure all subwidgets
	self.__nearest.configure(color=nearest)
	self.__typein.configure(color=rgbtuple)
	self.__reds.configure(color=rgbtuple)
	self.__greens.configure(color=rgbtuple)
	self.__blues.configure(color=rgbtuple)
	delegate = self['delegate']
	if delegate:
	    delegate.set_color(self, rgbtuple)

    #
    # PRIVATE INTERFACE
    #

    def __set_color(self):
	self.set_color(self, self['color'])

    def __buttonpress(self, event=None):
	self.__chip.configure(relief=SUNKEN)

    def __buttonrelease(self, event=None):
	self.__chip.configure(relief=RAISED)
	color = self.__nearest['color']
	rgbtuple = self.__colordb.find_byname(color)
	self.set_color(self, rgbtuple)

    def __quit(self, event=None):
	self.__parent.quit()

    def __popup_about(self, event=None):
	if not self.__about_dialog:
	    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')
	    self.__about_dialog = Pmw.AboutDialog(
		applicationname='Pynche -- the PYthonically Natural\n'
		'Color and Hue Editor')
	self.__about_dialog.show()

    def __popup_options(self, event=None):
	if not self.__options_dialog:
	    self.__options_dialog = PyncheOptions(
                title='Pynche Options',
                applycommand=self.__apply)
        # pop up the window, non-modal
        self.__options_dialog.deiconify()

    def __apply(self):
	self.__typein.set_update_on_typing(
	    self.__options_dialog.get_value('typing'))
	flag = self.__options_dialog.get_value('dragging')
	for strip in (self.__reds, self.__greens, self.__blues):
	    strip.set_update_while_dragging(flag)