blob: 77fb1878fd2416e95be7fef88ac326a30511c546 [file] [log] [blame]
Barry Warsawf67a50c1998-02-18 00:05:59 +00001import string
Barry Warsaw9d882bc1998-02-12 19:51:57 +00002from Tkinter import *
3import Pmw
4import ColorDB
5
Barry Warsaw4c2fab51998-02-18 16:22:22 +00006# Load this script into the Tcl interpreter and call it in
7# StripWidget.set_color(). This is about as fast as it can be with the
8# current _tkinter.c interface, which doesn't support Tcl Objects.
9TCLPROC = '''\
10proc setcolor {canv colors} {
11 set i 1
12 foreach c $colors {
13 $canv itemconfigure $i -fill $c -outline $c
14 incr i
15 }
16}
17'''
18
Barry Warsawee6d8a51998-03-17 15:59:26 +000019# Tcl event types
20BTNDOWN = 4
21BTNUP = 5
22BTNDRAG = 6
23
Barry Warsaw4c2fab51998-02-18 16:22:22 +000024
Barry Warsawf67a50c1998-02-18 00:05:59 +000025
Barry Warsaw9d882bc1998-02-12 19:51:57 +000026class LeftArrow:
27 _ARROWWIDTH = 30
28 _ARROWHEIGHT = 15
29 _YOFFSET = 13
30 _TEXTYOFFSET = 1
31 _TAG = ('leftarrow',)
32
33 def __init__(self, canvas, x):
34 self._canvas = canvas
35 self.__arrow, self.__text = self._create(x)
36 self.move_to(x)
37
38 def _create(self, x):
39 arrow = self._canvas.create_line(
40 x, self._ARROWHEIGHT + self._YOFFSET,
41 x, self._YOFFSET,
42 x + self._ARROWWIDTH, self._YOFFSET,
43 arrow='first',
44 width=3.0,
45 tags=self._TAG)
46 text = self._canvas.create_text(
47 x + self._ARROWWIDTH + 13,
48 self._ARROWHEIGHT - self._TEXTYOFFSET,
Barry Warsaw35ae8641998-02-13 21:28:47 +000049 tags=self._TAG,
Barry Warsaw9d882bc1998-02-12 19:51:57 +000050 text='128')
51 return arrow, text
52
53 def _x(self):
54 coords = self._canvas.coords(self._TAG)
55 assert coords
56 return coords[0]
57
58 def move_to(self, x):
59 deltax = x - self._x()
60 self._canvas.move(self._TAG, deltax, 0)
61
Barry Warsaw35ae8641998-02-13 21:28:47 +000062 def set_text(self, text):
63 self._canvas.itemconfigure(self.__text, text=text)
64
Barry Warsaw9d882bc1998-02-12 19:51:57 +000065
66class RightArrow(LeftArrow):
67 _TAG = ('rightarrow',)
68
69 def _create(self, x):
70 arrow = self._canvas.create_line(
71 x, self._YOFFSET,
72 x + self._ARROWWIDTH, self._YOFFSET,
73 x + self._ARROWWIDTH, self._ARROWHEIGHT + self._YOFFSET,
74 arrow='last',
75 width=3.0,
76 tags=self._TAG)
77 text = self._canvas.create_text(
Barry Warsaw35ae8641998-02-13 21:28:47 +000078 x - self._ARROWWIDTH + 15, # TBD: kludge
Barry Warsaw9d882bc1998-02-12 19:51:57 +000079 self._ARROWHEIGHT - self._TEXTYOFFSET,
Barry Warsaw35ae8641998-02-13 21:28:47 +000080 text='128',
81 tags=self._TAG)
Barry Warsaw9d882bc1998-02-12 19:51:57 +000082 return arrow, text
83
84 def _x(self):
85 coords = self._canvas.bbox(self._TAG)
86 assert coords
87 return coords[2] - 6 # TBD: kludge
88
89
90
91class StripWidget(Pmw.MegaWidget):
92 _CHIPHEIGHT = 50
93 _CHIPWIDTH = 10
94 _NUMCHIPS = 40
95
96 def __init__(self, parent=None, **kw):
Barry Warsawee6d8a51998-03-17 15:59:26 +000097 self.__lastchip = None
98
Barry Warsawf67a50c1998-02-18 00:05:59 +000099 options = (('color', (128, 128, 128), self.__set_color),
100 ('delegate', None, self.__set_delegate),
101 ('chipwidth', self._CHIPWIDTH, Pmw.INITOPT),
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000102 ('chipheight', self._CHIPHEIGHT, Pmw.INITOPT),
Barry Warsawf67a50c1998-02-18 00:05:59 +0000103 ('numchips', self._NUMCHIPS, Pmw.INITOPT),
104 ('generator', None, Pmw.INITOPT),
105 ('axis', None, Pmw.INITOPT),
106 ('label', '', Pmw.INITOPT),
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000107 )
108 self.defineoptions(kw, options)
109
110 Pmw.MegaWidget.__init__(self, parent)
111 interiorarg = (self.interior(),)
112
113 # group component contains a convas containing a bunch of objects
114 # (moveable arrow + text label, relief'd rectangle color chips)
115 chipwidth = self.__chipwidth = self['chipwidth']
116 chipheight = self.__chipheight = self['chipheight']
117 numchips = self.__numchips = self['numchips']
118
119 canvaswidth = numchips * (chipwidth + 1)
Barry Warsawbc689301998-02-17 03:09:40 +0000120 canvasheight = chipheight + 43 # TBD: Kludge
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000121
Barry Warsawbc689301998-02-17 03:09:40 +0000122 # create the canvas and pack it
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000123 canvas = self.__canvas = Canvas(
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000124 parent,
125 width=canvaswidth,
Barry Warsawbc689301998-02-17 03:09:40 +0000126 height=canvasheight,
127## borderwidth=2,
128## relief=GROOVE
129 )
130
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000131 canvas.pack()
Barry Warsawee6d8a51998-03-17 15:59:26 +0000132 canvas.bind('<ButtonPress-1>', self.__select_chip)
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000133 canvas.bind('<ButtonRelease-1>', self.__select_chip)
Barry Warsawee6d8a51998-03-17 15:59:26 +0000134 canvas.bind('<B1-Motion>', self.__select_chip)
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000135
Barry Warsaw4c2fab51998-02-18 16:22:22 +0000136 # Load a proc into the Tcl interpreter. This is used in the
137 # set_color() method to speed up setting the chip colors.
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000138 canvas.tk.eval(TCLPROC)
Barry Warsaw4c2fab51998-02-18 16:22:22 +0000139
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000140 # create the color strip
141 chips = self.__chips = []
142 x = 1
143 y = 30
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000144 tags = ('chip',)
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000145 for c in range(self.__numchips):
Barry Warsawf67a50c1998-02-18 00:05:59 +0000146 color = 'grey'
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000147 rect = canvas.create_rectangle(
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000148 x, y, x+chipwidth, y+chipheight,
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000149 fill=color, outline=color,
150 tags=tags)
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000151
152 x = x + chipwidth + 1 # for outline
Barry Warsawf67a50c1998-02-18 00:05:59 +0000153 chips.append(color)
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000154
Barry Warsawbc689301998-02-17 03:09:40 +0000155 # create the string tag
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000156 self.__label = canvas.create_text(
Barry Warsawbc689301998-02-17 03:09:40 +0000157 3, y + chipheight + 8,
158 text=self['label'],
159 anchor=W)
160
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000161 # create the arrow and text item
162 chipx = self.__arrow_x(0)
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000163 self.__leftarrow = LeftArrow(canvas, chipx)
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000164
165 chipx = self.__arrow_x(len(chips) - 1)
Barry Warsaw4435d5a1998-02-18 17:00:24 +0000166 self.__rightarrow = RightArrow(canvas, chipx)
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000167
168 self.__generator = self['generator']
Barry Warsaw35ae8641998-02-13 21:28:47 +0000169 self.__axis = self['axis']
170 assert self.__axis in (0, 1, 2)
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000171 self.initialiseoptions(StripWidget)
Barry Warsawf67a50c1998-02-18 00:05:59 +0000172 self.__delegate = self['delegate']
Barry Warsawa341fc31998-03-17 16:19:05 +0000173 self.__update_while_dragging = 0
Barry Warsaw9d882bc1998-02-12 19:51:57 +0000174
175 def __set_color(self):
176 rgbtuple = self['color']
Barry Warsawbc689301998-02-17 03:09:40 +0000177 self.set_color(self, rgbtuple)
178
179 def __arrow_x(self, chipnum):
Barry Warsawf67a50c1998-02-18 00:05:59 +0000180 coords = self.__canvas.coords(chipnum+1)
Barry Warsawbc689301998-02-17 03:09:40 +0000181 assert coords
182 x0, y0, x1, y1 = coords
183 return (x1 + x0) / 2.0
184
185 def __select_chip(self, event=None):
Barry Warsawee6d8a51998-03-17 15:59:26 +0000186 if self.__delegate:
187 x = event.x
188 y = event.y
189 canvas = self.__canvas
190 chip = canvas.find_overlapping(x, y, x, y)
191 if chip and (1 <= chip[0] <= self.__numchips):
192 color = self.__chips[chip[0]-1]
193 rgbtuple = ColorDB.rrggbb_to_triplet(color)
194 etype = int(event.type)
195 if (etype == BTNUP or self.__update_while_dragging):
196 # update everyone
197 self.__delegate.set_color(self, rgbtuple)
198 else:
199 # just track the arrows
200 self.__trackarrow(chip[0], rgbtuple)
Barry Warsaw70787ed1998-03-16 23:08:53 +0000201
Barry Warsawf67a50c1998-02-18 00:05:59 +0000202
203 def __set_delegate(self):
204 self.__delegate = self['delegate']
Barry Warsawbc689301998-02-17 03:09:40 +0000205
206
Barry Warsawee6d8a51998-03-17 15:59:26 +0000207 def __trackarrow(self, chip, rgbtuple):
208 # invert the last chip
209 if self.__lastchip is not None:
210 color = self.__canvas.itemcget(self.__lastchip, 'fill')
211 self.__canvas.itemconfigure(self.__lastchip, outline=color)
212 self.__lastchip = chip
Barry Warsaw35ae8641998-02-13 21:28:47 +0000213
Barry Warsawf67a50c1998-02-18 00:05:59 +0000214 # get the arrow's text
215 coloraxis = rgbtuple[self.__axis]
216 text = repr(coloraxis)
217
218 # move the arrow, and set it's text
219 if coloraxis <= 128:
220 # use the left chip
221 self.__leftarrow.set_text(text)
222 self.__leftarrow.move_to(self.__arrow_x(chip-1))
223 self.__rightarrow.move_to(-100)
224 else:
225 # use the right chip
226 self.__rightarrow.set_text(text)
227 self.__rightarrow.move_to(self.__arrow_x(chip-1))
228 self.__leftarrow.move_to(-100)
229 # and set the chip's outline
230 pmwrgb = ColorDB.triplet_to_pmwrgb(rgbtuple)
231 b = Pmw.Color.rgb2brightness(pmwrgb)
232 if b <= 0.5:
233 outline = 'white'
234 else:
235 outline = 'black'
236 self.__canvas.itemconfigure(chip, outline=outline)
Barry Warsaw70787ed1998-03-16 23:08:53 +0000237
Barry Warsawee6d8a51998-03-17 15:59:26 +0000238
239 #
240 # public interface
241 #
242
243 def set_color(self, obj, rgbtuple):
244 red, green, blue = rgbtuple
245 assert self.__generator
246 i = 1
247 chip = 0
248 chips = self.__chips = []
249 tclcmd = []
250 tk = self.__canvas.tk
251
252 for t in self.__generator(self.__numchips, rgbtuple):
253 rrggbb = ColorDB.triplet_to_rrggbb(t)
254 chips.append(rrggbb)
255 tred, tgreen, tblue = t
256 if tred <= red and tgreen <= green and tblue <= blue:
257 chip = i
258 i = i + 1
259 # call the raw tcl script
260 colors = string.join(chips)
261 tk.eval('setcolor %s {%s}' % (self.__canvas._w, colors))
262
263 # move the arrows around
264 self.__trackarrow(chip, rgbtuple)
265
Barry Warsaw70787ed1998-03-16 23:08:53 +0000266 def set_update_while_dragging(self, flag):
267 self.__update_while_dragging = flag