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