blob: db825e32c3dd611d4ba51dffe02840cf8f006098 [file] [log] [blame]
Barry Warsawf67a50c1998-02-18 00:05:59 +00001import string
Barry Warsaw9d882bc1998-02-12 19:51:57 +00002from Tkinter import *
Barry Warsaw9d882bc1998-02-12 19:51:57 +00003import ColorDB
4
Barry Warsaw4c2fab51998-02-18 16:22:22 +00005# Load this script into the Tcl interpreter and call it in
6# StripWidget.set_color(). This is about as fast as it can be with the
7# current _tkinter.c interface, which doesn't support Tcl Objects.
8TCLPROC = '''\
9proc setcolor {canv colors} {
10 set i 1
11 foreach c $colors {
12 $canv itemconfigure $i -fill $c -outline $c
13 incr i
14 }
15}
16'''
17
Barry Warsawee6d8a51998-03-17 15:59:26 +000018# Tcl event types
19BTNDOWN = 4
20BTNUP = 5
21BTNDRAG = 6
22
Barry Warsaw4c2fab51998-02-18 16:22:22 +000023
Barry Warsaw0dc9c921998-09-28 22:42:44 +000024def constant(numchips):
25 step = 255.0 / (numchips - 1)
26 start = 0.0
27 seq = []
28 while numchips > 0:
29 seq.append(int(start))
30 start = start + step
31 numchips = numchips - 1
32 return seq
33
34# red variations, green+blue = cyan constant
35def constant_cyan_generator(numchips, red, green, blue):
36 seq = constant(numchips)
37 return map(None, seq, [green] * numchips, [blue] * numchips)
38
39# green variations, red+blue = magenta constant
40def constant_magenta_generator(numchips, red, green, blue):
41 seq = constant(numchips)
42 return map(None, [red] * numchips, seq, [blue] * numchips)
43
44# blue variations, red+green = yellow constant
45def constant_yellow_generator(numchips, red, green, blue):
46 seq = constant(numchips)
47 return map(None, [red] * numchips, [green] * numchips, seq)
48
49
50
Barry Warsawf67a50c1998-02-18 00:05:59 +000051
Barry Warsaw9d882bc1998-02-12 19:51:57 +000052class LeftArrow:
53 _ARROWWIDTH = 30
54 _ARROWHEIGHT = 15
55 _YOFFSET = 13
56 _TEXTYOFFSET = 1
57 _TAG = ('leftarrow',)
58
59 def __init__(self, canvas, x):
60 self._canvas = canvas
61 self.__arrow, self.__text = self._create(x)
62 self.move_to(x)
63
64 def _create(self, x):
65 arrow = self._canvas.create_line(
66 x, self._ARROWHEIGHT + self._YOFFSET,
67 x, self._YOFFSET,
68 x + self._ARROWWIDTH, self._YOFFSET,
69 arrow='first',
70 width=3.0,
71 tags=self._TAG)
72 text = self._canvas.create_text(
73 x + self._ARROWWIDTH + 13,
74 self._ARROWHEIGHT - self._TEXTYOFFSET,
Barry Warsaw35ae8641998-02-13 21:28:47 +000075 tags=self._TAG,
Barry Warsaw9d882bc1998-02-12 19:51:57 +000076 text='128')
77 return arrow, text
78
79 def _x(self):
80 coords = self._canvas.coords(self._TAG)
81 assert coords
82 return coords[0]
83
84 def move_to(self, x):
85 deltax = x - self._x()
86 self._canvas.move(self._TAG, deltax, 0)
87
Barry Warsaw35ae8641998-02-13 21:28:47 +000088 def set_text(self, text):
89 self._canvas.itemconfigure(self.__text, text=text)
90
Barry Warsaw9d882bc1998-02-12 19:51:57 +000091
92class RightArrow(LeftArrow):
93 _TAG = ('rightarrow',)
94
95 def _create(self, x):
96 arrow = self._canvas.create_line(
97 x, self._YOFFSET,
98 x + self._ARROWWIDTH, self._YOFFSET,
99 x + self._ARROWWIDTH, self._ARROWHEIGHT + self._YOFFSET,
100 arrow='last',
101 width=3.0,
102 tags=self._TAG)
103 text = self._canvas.create_text(
Barry Warsaw35ae8641998-02-13 21:28:47 +0000104 x - self._ARROWWIDTH + 15, # TBD: kludge
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000105 self._ARROWHEIGHT - self._TEXTYOFFSET,
Barry Warsaw35ae8641998-02-13 21:28:47 +0000106 text='128',
107 tags=self._TAG)
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000108 return arrow, text
109
110 def _x(self):
111 coords = self._canvas.bbox(self._TAG)
112 assert coords
113 return coords[2] - 6 # TBD: kludge
114
115
116
Barry Warsaw6a3ea741998-09-28 20:58:06 +0000117class StripWidget:
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000118 _CHIPHEIGHT = 50
119 _CHIPWIDTH = 10
120 _NUMCHIPS = 40
121
Barry Warsaw6a3ea741998-09-28 20:58:06 +0000122 def __init__(self, switchboard,
123 parent = None,
Barry Warsaw0dc9c921998-09-28 22:42:44 +0000124 chipwidth = _CHIPWIDTH,
125 chipheight = _CHIPHEIGHT,
126 numchips = _NUMCHIPS,
Barry Warsaw6a3ea741998-09-28 20:58:06 +0000127 generator = None,
128 axis = None,
Barry Warsawd3441651998-10-01 03:08:07 +0000129 label = '',
130 uwdvar = None):
Barry Warsaw5177c481998-09-28 21:01:55 +0000131 # instance variables
132 self.__generator = generator
133 self.__axis = axis
Barry Warsaw0dc9c921998-09-28 22:42:44 +0000134 self.__numchips = numchips
Barry Warsaw5177c481998-09-28 21:01:55 +0000135 assert self.__axis in (0, 1, 2)
Barry Warsawd3441651998-10-01 03:08:07 +0000136 self.__uwd = uwdvar
Barry Warsaw6a3ea741998-09-28 20:58:06 +0000137 # the last chip selected
Barry Warsawee6d8a51998-03-17 15:59:26 +0000138 self.__lastchip = None
Barry Warsaw6a3ea741998-09-28 20:58:06 +0000139 self.__sb = switchboard
Barry Warsaw5177c481998-09-28 21:01:55 +0000140
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000141 canvaswidth = numchips * (chipwidth + 1)
Barry Warsawbc689301998-02-17 03:09:40 +0000142 canvasheight = chipheight + 43 # TBD: Kludge
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000143
Barry Warsawbc689301998-02-17 03:09:40 +0000144 # create the canvas and pack it
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000145 canvas = self.__canvas = Canvas(
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000146 parent,
147 width=canvaswidth,
Barry Warsawbc689301998-02-17 03:09:40 +0000148 height=canvasheight,
149## borderwidth=2,
150## relief=GROOVE
151 )
152
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000153 canvas.pack()
Barry Warsawee6d8a51998-03-17 15:59:26 +0000154 canvas.bind('<ButtonPress-1>', self.__select_chip)
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000155 canvas.bind('<ButtonRelease-1>', self.__select_chip)
Barry Warsawee6d8a51998-03-17 15:59:26 +0000156 canvas.bind('<B1-Motion>', self.__select_chip)
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000157
Barry Warsaw4c2fab51998-02-18 16:22:22 +0000158 # Load a proc into the Tcl interpreter. This is used in the
159 # set_color() method to speed up setting the chip colors.
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000160 canvas.tk.eval(TCLPROC)
Barry Warsaw4c2fab51998-02-18 16:22:22 +0000161
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000162 # create the color strip
163 chips = self.__chips = []
164 x = 1
165 y = 30
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000166 tags = ('chip',)
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000167 for c in range(self.__numchips):
Barry Warsawf67a50c1998-02-18 00:05:59 +0000168 color = 'grey'
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000169 rect = canvas.create_rectangle(
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000170 x, y, x+chipwidth, y+chipheight,
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000171 fill=color, outline=color,
172 tags=tags)
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000173 x = x + chipwidth + 1 # for outline
Barry Warsawf67a50c1998-02-18 00:05:59 +0000174 chips.append(color)
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000175
Barry Warsaw6a3ea741998-09-28 20:58:06 +0000176 # create the strip label
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000177 self.__label = canvas.create_text(
Barry Warsawbc689301998-02-17 03:09:40 +0000178 3, y + chipheight + 8,
Barry Warsaw0dc9c921998-09-28 22:42:44 +0000179 text=label,
Barry Warsawbc689301998-02-17 03:09:40 +0000180 anchor=W)
181
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000182 # create the arrow and text item
183 chipx = self.__arrow_x(0)
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000184 self.__leftarrow = LeftArrow(canvas, chipx)
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000185
186 chipx = self.__arrow_x(len(chips) - 1)
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000187 self.__rightarrow = RightArrow(canvas, chipx)
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000188
Barry Warsawbc689301998-02-17 03:09:40 +0000189 def __arrow_x(self, chipnum):
Barry Warsawf67a50c1998-02-18 00:05:59 +0000190 coords = self.__canvas.coords(chipnum+1)
Barry Warsawbc689301998-02-17 03:09:40 +0000191 assert coords
192 x0, y0, x1, y1 = coords
193 return (x1 + x0) / 2.0
194
Barry Warsaw0dc9c921998-09-28 22:42:44 +0000195 # Invoked when one of the chips is clicked. This should just tell the
196 # switchboard to set the color on all the output components
Barry Warsawbc689301998-02-17 03:09:40 +0000197 def __select_chip(self, event=None):
Barry Warsaw0dc9c921998-09-28 22:42:44 +0000198 x = event.x
199 y = event.y
200 canvas = self.__canvas
201 chip = canvas.find_overlapping(x, y, x, y)
202 if chip and (1 <= chip[0] <= self.__numchips):
203 color = self.__chips[chip[0]-1]
204 red, green, blue = ColorDB.rrggbb_to_triplet(color)
205 etype = int(event.type)
Barry Warsawd3441651998-10-01 03:08:07 +0000206 if (etype == BTNUP or self.__uwd.get()):
Barry Warsaw0dc9c921998-09-28 22:42:44 +0000207 # update everyone
208 self.__sb.update_views(red, green, blue)
209 else:
210 # just track the arrows
211 self.__trackarrow(chip[0], (red, green, blue))
Barry Warsawbc689301998-02-17 03:09:40 +0000212
Barry Warsawee6d8a51998-03-17 15:59:26 +0000213 def __trackarrow(self, chip, rgbtuple):
214 # invert the last chip
215 if self.__lastchip is not None:
216 color = self.__canvas.itemcget(self.__lastchip, 'fill')
217 self.__canvas.itemconfigure(self.__lastchip, outline=color)
218 self.__lastchip = chip
Barry Warsawf67a50c1998-02-18 00:05:59 +0000219 # get the arrow's text
220 coloraxis = rgbtuple[self.__axis]
221 text = repr(coloraxis)
Barry Warsawf67a50c1998-02-18 00:05:59 +0000222 # move the arrow, and set it's text
223 if coloraxis <= 128:
Barry Warsaw6a3ea741998-09-28 20:58:06 +0000224 # use the left arrow
Barry Warsawf67a50c1998-02-18 00:05:59 +0000225 self.__leftarrow.set_text(text)
226 self.__leftarrow.move_to(self.__arrow_x(chip-1))
227 self.__rightarrow.move_to(-100)
228 else:
Barry Warsaw6a3ea741998-09-28 20:58:06 +0000229 # use the right arrow
Barry Warsawf67a50c1998-02-18 00:05:59 +0000230 self.__rightarrow.set_text(text)
231 self.__rightarrow.move_to(self.__arrow_x(chip-1))
232 self.__leftarrow.move_to(-100)
233 # and set the chip's outline
Barry Warsaw6a3ea741998-09-28 20:58:06 +0000234 brightness = ColorDB.triplet_to_brightness(rgbtuple)
Barry Warsaw26f4b5d1998-09-28 22:52:02 +0000235 if brightness <= 128:
Barry Warsawf67a50c1998-02-18 00:05:59 +0000236 outline = 'white'
237 else:
238 outline = 'black'
239 self.__canvas.itemconfigure(chip, outline=outline)
Barry Warsaw70787ed1998-03-16 23:08:53 +0000240
Barry Warsawee6d8a51998-03-17 15:59:26 +0000241
Barry Warsaw6a3ea741998-09-28 20:58:06 +0000242 def update_yourself(self, red, green, blue):
Barry Warsawee6d8a51998-03-17 15:59:26 +0000243 assert self.__generator
244 i = 1
245 chip = 0
246 chips = self.__chips = []
247 tclcmd = []
248 tk = self.__canvas.tk
Barry Warsaw6a3ea741998-09-28 20:58:06 +0000249 # get the red, green, and blue components for all chips
Barry Warsaw0dc9c921998-09-28 22:42:44 +0000250 for t in self.__generator(self.__numchips, red, green, blue):
Barry Warsawee6d8a51998-03-17 15:59:26 +0000251 rrggbb = ColorDB.triplet_to_rrggbb(t)
252 chips.append(rrggbb)
253 tred, tgreen, tblue = t
254 if tred <= red and tgreen <= green and tblue <= blue:
255 chip = i
256 i = i + 1
257 # call the raw tcl script
258 colors = string.join(chips)
259 tk.eval('setcolor %s {%s}' % (self.__canvas._w, colors))
Barry Warsawee6d8a51998-03-17 15:59:26 +0000260 # move the arrows around
Barry Warsaw6a3ea741998-09-28 20:58:06 +0000261 self.__trackarrow(chip, (red, green, blue))
Barry Warsawee6d8a51998-03-17 15:59:26 +0000262
Barry Warsaw0dc9c921998-09-28 22:42:44 +0000263
264class StripViewer:
265 def __init__(self, switchboard, parent=None):
266 self.__sb = switchboard
Barry Warsawd7d47251998-09-29 17:36:43 +0000267 # create a frame inside the parent
Barry Warsaw65f0b6b1998-10-01 14:26:04 +0000268 self.__frame = Frame(parent) #, relief=GROOVE, borderwidth=2)
269 self.__frame.grid(row=1, column=0, columnspan=2, sticky='EW')
Barry Warsawd3441651998-10-01 03:08:07 +0000270 uwd = BooleanVar()
Barry Warsawd7d47251998-09-29 17:36:43 +0000271 self.__reds = StripWidget(switchboard, self.__frame,
Barry Warsaw0dc9c921998-09-28 22:42:44 +0000272 generator=constant_cyan_generator,
273 axis=0,
Barry Warsawd3441651998-10-01 03:08:07 +0000274 label='Red Variations',
275 uwdvar=uwd)
Barry Warsaw0dc9c921998-09-28 22:42:44 +0000276
Barry Warsawd7d47251998-09-29 17:36:43 +0000277 self.__greens = StripWidget(switchboard, self.__frame,
Barry Warsaw0dc9c921998-09-28 22:42:44 +0000278 generator=constant_magenta_generator,
279 axis=1,
Barry Warsawd3441651998-10-01 03:08:07 +0000280 label='Green Variations',
281 uwdvar=uwd)
Barry Warsaw0dc9c921998-09-28 22:42:44 +0000282
Barry Warsawd7d47251998-09-29 17:36:43 +0000283 self.__blues = StripWidget(switchboard, self.__frame,
Barry Warsaw0dc9c921998-09-28 22:42:44 +0000284 generator=constant_yellow_generator,
285 axis=2,
Barry Warsawd3441651998-10-01 03:08:07 +0000286 label='Blue Variations',
287 uwdvar=uwd)
288 self.__uwd = Checkbutton(self.__frame,
289 text='Update while dragging',
290 variable=uwd)
291 self.__uwd.pack()
Barry Warsaw65f0b6b1998-10-01 14:26:04 +0000292 self.__div = Frame(self.__frame,
293 height=2,
294 borderwidth=2,
295 relief=RAISED)
296 self.__div.pack(expand=1, fill=X)
Barry Warsaw0dc9c921998-09-28 22:42:44 +0000297
298 def update_yourself(self, red, green, blue):
299 self.__reds.update_yourself(red, green, blue)
300 self.__greens.update_yourself(red, green, blue)
301 self.__blues.update_yourself(red, green, blue)