blob: f988ce7a7a02ee6f70102cb4849204f8003cf1a8 [file] [log] [blame]
Just van Rossumf376ef02001-11-18 14:12:43 +00001from Carbon import App, Evt, Qd, QuickDraw, Win
Just van Rossum40f9b7b1999-01-30 22:39:17 +00002import string
3from types import *
4import sys
5
Just van Rossum2e9e71f2001-11-02 19:09:34 +00006class WidgetsError(Exception): pass
Just van Rossum40f9b7b1999-01-30 22:39:17 +00007
8DEBUG = 0
9
Just van Rossum2e9e71f2001-11-02 19:09:34 +000010
Just van Rossum40f9b7b1999-01-30 22:39:17 +000011class Widget:
12
13 """Base class for all widgets."""
14
15 _selectable = 0
16
17 def __init__(self, possize):
18 self._widgets = []
19 self._widgetsdict = {}
20 self._possize = possize
21 self._bounds = None
22 self._visible = 1
23 self._enabled = 0
24 self._selected = 0
25 self._activated = 0
26 self._callback = None
27 self._parent = None
28 self._parentwindow = None
29 self._bindings = {}
30 self._backcolor = None
31
32 def show(self, onoff):
33 self._visible = onoff
34 for w in self._widgets:
35 w.show(onoff)
36 if self._parentwindow is not None and self._parentwindow.wid is not None:
37 self.SetPort()
38 if onoff:
39 self.draw()
40 else:
41 Qd.EraseRect(self._bounds)
42
43 def draw(self, visRgn = None):
44 if self._visible:
45 # draw your stuff here
46 pass
47
48 def getpossize(self):
49 return self._possize
50
51 def getbounds(self):
52 return self._bounds
53
54 def move(self, x, y = None):
55 """absolute move"""
56 if y == None:
57 x, y = x
58 if type(self._possize) <> TupleType:
59 raise WidgetsError, "can't move widget with bounds function"
60 l, t, r, b = self._possize
61 self.resize(x, y, r, b)
62
63 def rmove(self, x, y = None):
64 """relative move"""
65 if y == None:
66 x, y = x
67 if type(self._possize) <> TupleType:
68 raise WidgetsError, "can't move widget with bounds function"
69 l, t, r, b = self._possize
70 self.resize(l + x, t + y, r, b)
71
72 def resize(self, *args):
73 if len(args) == 1:
74 if type(args[0]) == FunctionType or type(args[0]) == MethodType:
75 self._possize = args[0]
76 else:
77 apply(self.resize, args[0])
78 elif len(args) == 2:
79 self._possize = (0, 0) + args
80 elif len(args) == 4:
81 self._possize = args
82 else:
83 raise TypeError, "wrong number of arguments"
84 self._calcbounds()
85
86 def open(self):
87 self._calcbounds()
88
89 def close(self):
90 del self._callback
91 del self._possize
92 del self._bindings
93 del self._parent
94 del self._parentwindow
95
96 def bind(self, key, callback):
97 """bind a key or an 'event' to a callback"""
98 if callback:
99 self._bindings[key] = callback
100 elif self._bindings.has_key(key):
101 del self._bindings[key]
102
103 def adjust(self, oldbounds):
104 self.SetPort()
Jack Jansen73023402001-01-23 14:58:20 +0000105 self.GetWindow().InvalWindowRect(oldbounds)
106 self.GetWindow().InvalWindowRect(self._bounds)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000107
108 def _calcbounds(self):
109 # calculate absolute bounds relative to the window origin from our
110 # abstract _possize attribute, which is either a 4-tuple or a callable object
111 oldbounds = self._bounds
112 pl, pt, pr, pb = self._parent._bounds
113 if callable(self._possize):
114 # _possize is callable, let it figure it out by itself: it should return
115 # the bounds relative to our parent widget.
116 width = pr - pl
117 height = pb - pt
118 self._bounds = Qd.OffsetRect(self._possize(width, height), pl, pt)
119 else:
120 # _possize must be a 4-tuple. This is where the algorithm by Peter Kriens and
121 # Petr van Blokland kicks in. (*** Parts of this algorithm are applied for
122 # patents by Ericsson, Sweden ***)
123 l, t, r, b = self._possize
124 # depending on the values of l(eft), t(op), r(right) and b(ottom),
125 # they mean different things:
126 if l < -1:
127 # l is less than -1, this mean it measures from the *right* of it's parent
128 l = pr + l
129 else:
130 # l is -1 or greater, this mean it measures from the *left* of it's parent
131 l = pl + l
132 if t < -1:
133 # t is less than -1, this mean it measures from the *bottom* of it's parent
134 t = pb + t
135 else:
136 # t is -1 or greater, this mean it measures from the *top* of it's parent
137 t = pt + t
138 if r > 1:
139 # r is greater than 1, this means r is the *width* of the widget
140 r = l + r
141 else:
142 # r is less than 1, this means it measures from the *right* of it's parent
143 r = pr + r
144 if b > 1:
145 # b is greater than 1, this means b is the *height* of the widget
146 b = t + b
147 else:
148 # b is less than 1, this means it measures from the *bottom* of it's parent
149 b = pb + b
150 self._bounds = (l, t, r, b)
151 if oldbounds and oldbounds <> self._bounds:
152 self.adjust(oldbounds)
153 for w in self._widgets:
154 w._calcbounds()
155
156 def test(self, point):
157 if Qd.PtInRect(point, self._bounds):
158 return 1
159
160 def click(self, point, modifiers):
161 pass
162
163 def findwidget(self, point, onlyenabled = 1):
164 if self.test(point):
165 for w in self._widgets:
166 widget = w.findwidget(point)
167 if widget is not None:
168 return widget
169 if self._enabled or not onlyenabled:
170 return self
171
172 def forall(self, methodname, *args):
173 for w in self._widgets:
174 rv = apply(w.forall, (methodname,) + args)
175 if rv:
176 return rv
177 if self._bindings.has_key("<" + methodname + ">"):
178 callback = self._bindings["<" + methodname + ">"]
179 rv = apply(callback, args)
180 if rv:
181 return rv
182 if hasattr(self, methodname):
183 method = getattr(self, methodname)
184 return apply(method, args)
185
186 def forall_butself(self, methodname, *args):
187 for w in self._widgets:
188 rv = apply(w.forall, (methodname,) + args)
189 if rv:
190 return rv
191
192 def forall_frombottom(self, methodname, *args):
193 if self._bindings.has_key("<" + methodname + ">"):
194 callback = self._bindings["<" + methodname + ">"]
195 rv = apply(callback, args)
196 if rv:
197 return rv
198 if hasattr(self, methodname):
199 method = getattr(self, methodname)
200 rv = apply(method, args)
201 if rv:
202 return rv
203 for w in self._widgets:
204 rv = apply(w.forall_frombottom, (methodname,) + args)
205 if rv:
206 return rv
207
208 def _addwidget(self, key, widget):
209 if widget in self._widgets:
210 raise ValueError, "duplicate widget"
211 if self._widgetsdict.has_key(key):
212 self._removewidget(key)
213 self._widgets.append(widget)
214 self._widgetsdict[key] = widget
215 widget._parent = self
216 self._setparentwindow(widget)
217 if self._parentwindow and self._parentwindow.wid:
218 widget.forall_frombottom("open")
Jack Jansen73023402001-01-23 14:58:20 +0000219 self.GetWindow().InvalWindowRect(widget._bounds)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000220
221 def _setparentwindow(self, widget):
222 widget._parentwindow = self._parentwindow
223 for w in widget._widgets:
224 self._setparentwindow(w)
225
226 def _removewidget(self, key):
227 if not self._widgetsdict.has_key(key):
228 raise KeyError, "no widget with key " + `key`
229 widget = self._widgetsdict[key]
230 for k in widget._widgetsdict.keys():
231 widget._removewidget(k)
232 if self._parentwindow._currentwidget == widget:
233 widget.select(0)
234 self._parentwindow._currentwidget = None
235 self.SetPort()
Jack Jansen73023402001-01-23 14:58:20 +0000236 self.GetWindow().InvalWindowRect(widget._bounds)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000237 widget.close()
238 del self._widgetsdict[key]
239 self._widgets.remove(widget)
240
241 def __setattr__(self, attr, value):
242 if type(value) == InstanceType and isinstance(value, Widget) and \
243 attr not in ("_currentwidget", "_lastrollover",
244 "_parent", "_parentwindow", "_defaultbutton"):
245 if hasattr(self, attr):
246 raise ValueError, "Can't replace existing attribute: " + attr
247 self._addwidget(attr, value)
248 self.__dict__[attr] = value
249
250 def __delattr__(self, attr):
251 if attr == "_widgetsdict":
252 raise AttributeError, "cannot delete attribute _widgetsdict"
253 if self._widgetsdict.has_key(attr):
254 self._removewidget(attr)
255 if self.__dict__.has_key(attr):
256 del self.__dict__[attr]
257 elif self.__dict__.has_key(attr):
258 del self.__dict__[attr]
259 else:
260 raise AttributeError, attr
261
262 def __setitem__(self, key, value):
263 self._addwidget(key, value)
264
265 def __getitem__(self, key):
266 if not self._widgetsdict.has_key(key):
267 raise KeyError, key
268 return self._widgetsdict[key]
269
270 def __delitem__(self, key):
271 self._removewidget(key)
272
273 def SetPort(self):
274 self._parentwindow.SetPort()
Jack Jansen73023402001-01-23 14:58:20 +0000275
276
277 def GetWindow(self):
278 return self._parentwindow.GetWindow()
279
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000280 def __del__(self):
281 if DEBUG:
282 print "%s instance deleted" % self.__class__.__name__
283
284 def _drawbounds(self):
285 Qd.FrameRect(self._bounds)
286
287
288class ClickableWidget(Widget):
289
290 """Base class for clickable widgets. (note: self._enabled must be true to receive click events.)"""
291
292 def click(self, point, modifiers):
293 pass
294
295 def enable(self, onoff):
296 self._enabled = onoff
297 self.SetPort()
298 self.draw()
299
300 def callback(self):
301 if self._callback:
302 return CallbackCall(self._callback, 1)
303
304
305class SelectableWidget(ClickableWidget):
306
307 """Base class for selectable widgets."""
308
309 _selectable = 1
310
311 def select(self, onoff, isclick = 0):
312 if onoff == self._selected:
313 return 1
314 if self._bindings.has_key("<select>"):
315 callback = self._bindings["<select>"]
316 if callback(onoff):
317 return 1
318 self._selected = onoff
319 if onoff:
320 if self._parentwindow._currentwidget is not None:
321 self._parentwindow._currentwidget.select(0)
322 self._parentwindow._currentwidget = self
323 else:
324 self._parentwindow._currentwidget = None
325
326 def key(self, char, event):
327 pass
328
329 def drawselframe(self, onoff):
330 if not self._parentwindow._hasselframes:
331 return
Just van Rossumf376ef02001-11-18 14:12:43 +0000332 App.DrawThemeFocusRect(self._bounds, onoff)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000333
334 def adjust(self, oldbounds):
335 self.SetPort()
336 if self._selected:
Jack Jansen73023402001-01-23 14:58:20 +0000337 self.GetWindow().InvalWindowRect(Qd.InsetRect(oldbounds, -3, -3))
338 self.GetWindow().InvalWindowRect(Qd.InsetRect(self._bounds, -3, -3))
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000339 else:
Jack Jansen73023402001-01-23 14:58:20 +0000340 self.GetWindow().InvalWindowRect(oldbounds)
341 self.GetWindow().InvalWindowRect(self._bounds)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000342
343
344class _Line(Widget):
345
346 def __init__(self, possize, thickness = 1):
347 Widget.__init__(self, possize)
348 self._thickness = thickness
349
350 def open(self):
351 self._calcbounds()
352 self.SetPort()
353 self.draw()
354
355 def draw(self, visRgn = None):
356 if self._visible:
357 Qd.PaintRect(self._bounds)
358
359 def _drawbounds(self):
360 pass
361
362class HorizontalLine(_Line):
363
364 def _calcbounds(self):
365 Widget._calcbounds(self)
366 l, t, r, b = self._bounds
367 self._bounds = l, t, r, t + self._thickness
368
369class VerticalLine(_Line):
370
371 def _calcbounds(self):
372 Widget._calcbounds(self)
373 l, t, r, b = self._bounds
374 self._bounds = l, t, l + self._thickness, b
375
376
377class Frame(Widget):
378
Jack Jansen362c7cd02002-11-30 00:01:29 +0000379 def __init__(self, possize, pattern = Qd.GetQDGlobalsBlack(), color = (0, 0, 0)):
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000380 Widget.__init__(self, possize)
381 self._framepattern = pattern
382 self._framecolor = color
383
384 def setcolor(self, color):
385 self._framecolor = color
386 self.SetPort()
387 self.draw()
388
389 def setpattern(self, pattern):
390 self._framepattern = pattern
391 self.SetPort()
392 self.draw()
393
394 def draw(self, visRgn = None):
395 if self._visible:
396 penstate = Qd.GetPenState()
397 Qd.PenPat(self._framepattern)
398 Qd.RGBForeColor(self._framecolor)
399 Qd.FrameRect(self._bounds)
400 Qd.RGBForeColor((0, 0, 0))
401 Qd.SetPenState(penstate)
402
403def _darkencolor((r, g, b)):
404 return 0.75 * r, 0.75 * g, 0.75 * b
405
406class BevelBox(Widget):
407
408 """'Platinum' beveled rectangle."""
409
410 def __init__(self, possize, color = (0xe000, 0xe000, 0xe000)):
411 Widget.__init__(self, possize)
412 self._color = color
413 self._darkercolor = _darkencolor(color)
414
415 def setcolor(self, color):
416 self._color = color
417 self.SetPort()
418 self.draw()
419
420 def draw(self, visRgn = None):
421 if self._visible:
422 l, t, r, b = Qd.InsetRect(self._bounds, 1, 1)
423 Qd.RGBForeColor(self._color)
424 Qd.PaintRect((l, t, r, b))
425 Qd.RGBForeColor(self._darkercolor)
426 Qd.MoveTo(l, b)
427 Qd.LineTo(r, b)
428 Qd.LineTo(r, t)
429 Qd.RGBForeColor((0, 0, 0))
430
431
432class Group(Widget):
433
434 """A container for subwidgets"""
435
436
437class HorizontalPanes(Widget):
438
439 """Panes, a.k.a. frames. Works a bit like a group. Devides the widget area into "panes",
440 which can be resized by the user by clicking and dragging between the subwidgets."""
441
442 _direction = 1
443
444 def __init__(self, possize, panesizes = None, gutter = 8):
445 """panesizes should be a tuple of numbers. The length of the tuple is the number of panes,
446 the items in the tuple are the relative sizes of these panes; these numbers should add up
447 to 1 (the total size of all panes)."""
Just van Rossum05a56b82001-10-31 12:55:07 +0000448 Widget.__init__(self, possize)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000449 self._panesizes = panesizes
450 self._gutter = gutter
451 self._enabled = 1
452 self.setuppanes()
453
454 #def open(self):
455 # self.installbounds()
456 # ClickableWidget.open(self)
457
458 def _calcbounds(self):
459 # hmmm. It should not neccesary be override _calcbounds :-(
460 self.installbounds()
461 Widget._calcbounds(self)
462
463 def setuppanes(self):
464 panesizes = self._panesizes
465 total = 0
466 if panesizes is not None:
467 #if len(self._widgets) <> len(panesizes):
468 # raise TypeError, 'number of widgets does not match number of panes'
469 for panesize in panesizes:
470 if not 0 < panesize < 1:
471 raise TypeError, 'pane sizes must be between 0 and 1, not including.'
472 total = total + panesize
473 if round(total, 4) <> 1.0:
474 raise TypeError, 'pane sizes must add up to 1'
475 else:
476 # XXX does not work!
477 step = 1.0 / len(self._widgets)
478 panesizes = []
479 for i in range(len(self._widgets)):
480 panesizes.append(step)
481 current = 0
482 self._panesizes = []
483 self._gutters = []
484 for panesize in panesizes:
485 if current:
486 self._gutters.append(current)
Jack Jansen34d11f02000-03-07 23:40:13 +0000487 self._panesizes.append((current, current + panesize))
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000488 current = current + panesize
489 self.makepanebounds()
490
491 def getpanesizes(self):
492 return map(lambda (fr, to): to-fr, self._panesizes)
493
494 boundstemplate = "lambda width, height: (0, height * %s + %d, width, height * %s + %d)"
495
496 def makepanebounds(self):
497 halfgutter = self._gutter / 2
498 self._panebounds = []
499 for i in range(len(self._panesizes)):
500 panestart, paneend = self._panesizes[i]
501 boundsstring = self.boundstemplate % (`panestart`, panestart and halfgutter,
502 `paneend`, (paneend <> 1.0) and -halfgutter)
503 self._panebounds.append(eval(boundsstring))
504
505 def installbounds(self):
506 #self.setuppanes()
507 for i in range(len(self._widgets)):
508 w = self._widgets[i]
509 w._possize = self._panebounds[i]
510 #if hasattr(w, "setuppanes"):
511 # w.setuppanes()
512 if hasattr(w, "installbounds"):
513 w.installbounds()
514
515 def rollover(self, point, onoff):
516 if onoff:
517 orgmouse = point[self._direction]
518 halfgutter = self._gutter / 2
519 l, t, r, b = self._bounds
520 if self._direction:
521 begin, end = t, b
522 else:
523 begin, end = l, r
524
525 i = self.findgutter(orgmouse, begin, end)
526 if i is None:
527 SetCursor("arrow")
528 else:
529 SetCursor(self._direction and 'vmover' or 'hmover')
530
531 def findgutter(self, orgmouse, begin, end):
532 tolerance = max(4, self._gutter) / 2
533 for i in range(len(self._gutters)):
534 pos = begin + (end - begin) * self._gutters[i]
535 if abs(orgmouse - pos) <= tolerance:
536 break
537 else:
538 return
539 return i
540
541 def click(self, point, modifiers):
542 # what a mess...
543 orgmouse = point[self._direction]
544 halfgutter = self._gutter / 2
545 l, t, r, b = self._bounds
546 if self._direction:
547 begin, end = t, b
548 else:
549 begin, end = l, r
550
551 i = self.findgutter(orgmouse, begin, end)
552 if i is None:
553 return
554
555 pos = orgpos = begin + (end - begin) * self._gutters[i] # init pos too, for fast click on border, bug done by Petr
556
557 minpos = self._panesizes[i][0]
558 maxpos = self._panesizes[i+1][1]
559 minpos = begin + (end - begin) * minpos + 64
560 maxpos = begin + (end - begin) * maxpos - 64
561 if minpos > orgpos and maxpos < orgpos:
562 return
563
564 #SetCursor("fist")
565 self.SetPort()
566 if self._direction:
567 rect = l, orgpos - 1, r, orgpos
568 else:
569 rect = orgpos - 1, t, orgpos, b
570
571 # track mouse --- XXX move to separate method?
572 Qd.PenMode(QuickDraw.srcXor)
Jack Jansen362c7cd02002-11-30 00:01:29 +0000573 Qd.PenPat(Qd.GetQDGlobalsGray())
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000574 Qd.PaintRect(rect)
575 lastpos = None
576 while Evt.Button():
577 pos = orgpos - orgmouse + Evt.GetMouse()[self._direction]
578 pos = max(pos, minpos)
579 pos = min(pos, maxpos)
580 if pos == lastpos:
581 continue
Jack Jansen362c7cd02002-11-30 00:01:29 +0000582 Qd.PenPat(Qd.GetQDGlobalsGray())
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000583 Qd.PaintRect(rect)
584 if self._direction:
585 rect = l, pos - 1, r, pos
586 else:
587 rect = pos - 1, t, pos, b
Jack Jansen362c7cd02002-11-30 00:01:29 +0000588 Qd.PenPat(Qd.GetQDGlobalsGray())
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000589 Qd.PaintRect(rect)
590 lastpos = pos
Jack Jansen362c7cd02002-11-30 00:01:29 +0000591 self._parentwindow.wid.GetWindowPort().QDFlushPortBuffer(None)
Just van Rossum1f1e7272001-12-08 10:37:40 +0000592 Evt.WaitNextEvent(0, 3)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000593 Qd.PaintRect(rect)
594 Qd.PenNormal()
595 SetCursor("watch")
596
597 newpos = (pos - begin) / float(end - begin)
598 self._gutters[i] = newpos
599 self._panesizes[i] = self._panesizes[i][0], newpos
600 self._panesizes[i+1] = newpos, self._panesizes[i+1][1]
601 self.makepanebounds()
602 self.installbounds()
603 self._calcbounds()
Just van Rossum1f1e7272001-12-08 10:37:40 +0000604
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000605
606class VerticalPanes(HorizontalPanes):
607 """see HorizontalPanes"""
608 _direction = 0
609 boundstemplate = "lambda width, height: (width * %s + %d, 0, width * %s + %d, height)"
610
611
612class ColorPicker(ClickableWidget):
613
614 """Color picker widget. Allows the user to choose a color."""
615
616 def __init__(self, possize, color = (0, 0, 0), callback = None):
617 ClickableWidget.__init__(self, possize)
618 self._color = color
619 self._callback = callback
620 self._enabled = 1
621
622 def click(self, point, modifiers):
623 if not self._enabled:
624 return
625 import ColorPicker
626 newcolor, ok = ColorPicker.GetColor("", self._color)
627 if ok:
628 self._color = newcolor
629 self.SetPort()
630 self.draw()
631 if self._callback:
632 return CallbackCall(self._callback, 0, self._color)
633
634 def set(self, color):
635 self._color = color
636 self.SetPort()
637 self.draw()
638
639 def get(self):
640 return self._color
641
642 def draw(self, visRgn=None):
643 if self._visible:
644 if not visRgn:
645 visRgn = self._parentwindow.wid.GetWindowPort().visRgn
Jack Jansen362c7cd02002-11-30 00:01:29 +0000646 Qd.PenPat(Qd.GetQDGlobalsGray())
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000647 rect = self._bounds
648 Qd.FrameRect(rect)
649 rect = Qd.InsetRect(rect, 3, 3)
650 Qd.PenNormal()
651 Qd.RGBForeColor(self._color)
652 Qd.PaintRect(rect)
653 Qd.RGBForeColor((0, 0, 0))
654
655
656# misc utils
657
658def CallbackCall(callback, mustfit, *args):
659 """internal helper routine for W"""
660 # XXX this function should die.
661 if type(callback) == FunctionType:
662 func = callback
663 maxargs = func.func_code.co_argcount
664 elif type(callback) == MethodType:
665 func = callback.im_func
666 maxargs = func.func_code.co_argcount - 1
667 else:
668 if callable(callback):
669 return apply(callback, args)
670 else:
671 raise TypeError, "uncallable callback object"
672
673 if func.func_defaults:
674 minargs = maxargs - len(func.func_defaults)
675 else:
676 minargs = maxargs
677 if minargs <= len(args) <= maxargs:
678 return apply(callback, args)
679 elif not mustfit and minargs == 0:
680 return callback()
681 else:
682 if mustfit:
683 raise TypeError, "callback accepts wrong number of arguments: " + `len(args)`
684 else:
685 raise TypeError, "callback accepts wrong number of arguments: 0 or " + `len(args)`
686
687
688def HasBaseClass(obj, class_):
689 try:
690 raise obj
691 except class_:
692 return 1
693 except:
694 pass
695 return 0
696
697
Just van Rossum761b6092002-11-24 01:01:07 +0000698#
699# To remove the dependence of Widgets.rsrc we hardcode the cursor
700# data below.
701#_cursors = {
702# "watch" : Qd.GetCursor(QuickDraw.watchCursor).data,
Jack Jansen362c7cd02002-11-30 00:01:29 +0000703# "arrow" : Qd.GetQDGlobalsArrow(),
Just van Rossum761b6092002-11-24 01:01:07 +0000704# "iBeam" : Qd.GetCursor(QuickDraw.iBeamCursor).data,
705# "cross" : Qd.GetCursor(QuickDraw.crossCursor).data,
706# "plus" : Qd.GetCursor(QuickDraw.plusCursor).data,
707# "hand" : Qd.GetCursor(468).data,
708# "fist" : Qd.GetCursor(469).data,
709# "hmover" : Qd.GetCursor(470).data,
710# "vmover" : Qd.GetCursor(471).data,
711# "zoomin" : Qd.GetCursor(472).data,
712# "zoomout" : Qd.GetCursor(473).data,
713# "zoom" : Qd.GetCursor(474).data,
714#}
715
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000716_cursors = {
Just van Rossum761b6092002-11-24 01:01:07 +0000717 'arrow':
718 '\x00\x00\x40\x00\x60\x00\x70\x00\x78\x00\x7c\x00\x7e\x00\x7f\x00'
719 '\x7f\x80\x7c\x00\x6c\x00\x46\x00\x06\x00\x03\x00\x03\x00\x00\x00'
720 '\xc0\x00\xe0\x00\xf0\x00\xf8\x00\xfc\x00\xfe\x00\xff\x00\xff\x80'
721 '\xff\xc0\xff\xe0\xfe\x00\xef\x00\xcf\x00\x87\x80\x07\x80\x03\x80'
722 '\x00\x01\x00\x01',
723 'cross':
724 '\x04\x00\x04\x00\x04\x00\x04\x00\x04\x00\xff\xe0\x04\x00\x04\x00'
725 '\x04\x00\x04\x00\x04\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00'
726 '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
727 '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
728 '\x00\x05\x00\x05',
729 'fist':
730 '\x00\x00\x00\x00\x0d\x80\x12\x70\x12\x4c\x12\x4a\x28\x0a\x28\x02'
731 '\x48\x02\x40\x02\x20\x02\x20\x04\x10\x04\x08\x08\x04\x08\x04\x08'
732 '\x00\x00\x00\x00\x0d\x80\x1f\xf0\x1f\xfc\x1f\xfe\x3f\xfe\x3f\xfe'
733 '\x7f\xfe\x7f\xfe\x3f\xfe\x3f\xfc\x1f\xfc\x0f\xf8\x07\xf8\x07\xf8'
734 '\x00\x09\x00\x08',
735 'hand':
736 '\x01\x80\x1a\x70\x26\x48\x26\x4a\x12\x4d\x12\x49\x68\x09\x98\x01'
737 '\x88\x02\x40\x02\x20\x02\x20\x04\x10\x04\x08\x08\x04\x08\x04\x08'
738 '\x01\x80\x1b\xf0\x3f\xf8\x3f\xfa\x1f\xff\x1f\xff\x6f\xff\xff\xff'
739 '\xff\xfe\x7f\xfe\x3f\xfe\x3f\xfc\x1f\xfc\x0f\xf8\x07\xf8\x07\xf8'
740 '\x00\x09\x00\x08',
741 'hmover':
742 '\x00\x00\x01\x80\x01\x80\x01\x80\x01\x80\x11\x88\x31\x8c\x7f\xfe'
743 '\x31\x8c\x11\x88\x01\x80\x01\x80\x01\x80\x01\x80\x00\x00\x00\x00'
744 '\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x1b\xd8\x3b\xdc\x7f\xfe\xff\xff'
745 '\x7f\xfe\x3b\xdc\x1b\xd8\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x00\x00'
746 '\x00\x07\x00\x07',
747 'iBeam':
748 '\x0c\x60\x02\x80\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00'
749 '\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x02\x80\x0c\x60'
750 '\x0c\x60\x02\x80\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00'
751 '\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x02\x80\x0c\x60'
752 '\x00\x04\x00\x07',
753 'plus':
754 '\x00\x00\x07\xc0\x04\x60\x04\x60\x04\x60\x7c\x7c\x43\x86\x42\x86'
755 '\x43\x86\x7c\x7e\x3c\x7e\x04\x60\x04\x60\x07\xe0\x03\xe0\x00\x00'
756 '\x0f\xc0\x0f\xe0\x0f\xf0\x0f\xf0\xff\xff\xff\xfe\xfc\x7f\xfc\x7f'
757 '\xfc\x7f\xff\xff\x7f\xff\x7f\xff\x0f\xf0\x0f\xf0\x07\xf0\x03\xe0'
758 '\x00\x08\x00\x08',
759 'vmover':
760 '\x00\x00\x01\x00\x03\x80\x07\xc0\x01\x00\x01\x00\x01\x00\x7f\xfc'
761 '\x7f\xfc\x01\x00\x01\x00\x01\x00\x07\xc0\x03\x80\x01\x00\x00\x00'
762 '\x01\x00\x03\x80\x07\xc0\x0f\xe0\x0f\xe0\x03\x80\xff\xfe\xff\xfe'
763 '\xff\xfe\xff\xfe\x03\x80\x0f\xe0\x0f\xe0\x07\xc0\x03\x80\x01\x00'
764 '\x00\x07\x00\x07',
765 'watch':
766 '\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x40\x80\x84\x40\x84\x40\x84\x60'
767 '\x9c\x60\x80\x40\x80\x40\x40\x80\x3f\x00\x3f\x00\x3f\x00\x3f\x00'
768 '\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x7f\x80\xff\xc0\xff\xc0\xff\xc0'
769 '\xff\xc0\xff\xc0\xff\xc0\x7f\x80\x3f\x00\x3f\x00\x3f\x00\x3f\x00'
770 '\x00\x08\x00\x08',
771 'zoom':
772 '\x0f\x00\x30\xc0\x40\x20\x40\x20\x80\x10\x80\x10\x80\x10\x80\x10'
773 '\x40\x20\x40\x20\x30\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
774 '\x0f\x00\x3f\xc0\x7f\xe0\x7f\xe0\xff\xf0\xff\xf0\xff\xf0\xff\xf0'
775 '\x7f\xe0\x7f\xe0\x3f\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
776 '\x00\x06\x00\x06',
777 'zoomin':
778 '\x0f\x00\x30\xc0\x40\x20\x46\x20\x86\x10\x9f\x90\x9f\x90\x86\x10'
779 '\x46\x20\x40\x20\x30\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
780 '\x0f\x00\x3f\xc0\x7f\xe0\x7f\xe0\xff\xf0\xff\xf0\xff\xf0\xff\xf0'
781 '\x7f\xe0\x7f\xe0\x3f\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
782 '\x00\x06\x00\x06',
783 'zoomout':
784 '\x0f\x00\x30\xc0\x40\x20\x40\x20\x80\x10\x9f\x90\x9f\x90\x80\x10'
785 '\x40\x20\x40\x20\x30\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
786 '\x0f\x00\x3f\xc0\x7f\xe0\x7f\xe0\xff\xf0\xff\xf0\xff\xf0\xff\xf0'
787 '\x7f\xe0\x7f\xe0\x3f\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
788 '\x00\x06\x00\x06',
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000789}
790
791def SetCursor(what):
792 """Set the cursorshape to any of these: 'arrow', 'cross', 'fist', 'hand', 'hmover', 'iBeam',
793 'plus', 'vmover', 'watch', 'zoom', 'zoomin', 'zoomout'."""
794 Qd.SetCursor(_cursors[what])