This commit was manufactured by cvs2svn to create tag
[python/dscho.git] / Mac / Lib / aetypes.py
blob8fe8cf9ac13fb8b8754f3e1dc5efd47e154ca298
1 """aetypes - Python objects representing various AE types."""
3 from Carbon.AppleEvents import *
4 import struct
5 from types import *
6 import string
9 # convoluted, since there are cyclic dependencies between this file and
10 # aetools_convert.
12 def pack(*args):
13 from aepack import pack
14 return apply(pack, args)
16 def IsSubclass(cls, base):
17 """Test whether CLASS1 is the same as or a subclass of CLASS2"""
18 # Loop to optimize for single inheritance
19 while 1:
20 if cls is base: return 1
21 if len(cls.__bases__) <> 1: break
22 cls = cls.__bases__[0]
23 # Recurse to cope with multiple inheritance
24 for c in cls.__bases__:
25 if IsSubclass(c, base): return 1
26 return 0
28 def IsInstance(x, cls):
29 """Test whether OBJECT is an instance of (a subclass of) CLASS"""
30 return type(x) is InstanceType and IsSubclass(x.__class__, cls)
32 def nice(s):
33 """'nice' representation of an object"""
34 if type(s) is StringType: return repr(s)
35 else: return str(s)
37 class Unknown:
38 """An uninterpreted AE object"""
40 def __init__(self, type, data):
41 self.type = type
42 self.data = data
44 def __repr__(self):
45 return "Unknown(%s, %s)" % (`self.type`, `self.data`)
47 def __aepack__(self):
48 return pack(self.data, self.type)
50 class Enum:
51 """An AE enumeration value"""
53 def __init__(self, enum):
54 self.enum = "%-4.4s" % str(enum)
56 def __repr__(self):
57 return "Enum(%s)" % `self.enum`
59 def __str__(self):
60 return string.strip(self.enum)
62 def __aepack__(self):
63 return pack(self.enum, typeEnumeration)
65 def IsEnum(x):
66 return IsInstance(x, Enum)
68 def mkenum(enum):
69 if IsEnum(enum): return enum
70 return Enum(enum)
72 class Boolean:
73 """An AE boolean value"""
75 def __init__(self, bool):
76 self.bool = (not not bool)
78 def __repr__(self):
79 return "Boolean(%s)" % `self.bool`
81 def __str__(self):
82 if self.bool:
83 return "True"
84 else:
85 return "False"
87 def __aepack__(self):
88 return pack(struct.pack('b', self.bool), 'bool')
90 def IsBoolean(x):
91 return IsInstance(x, Boolean)
93 def mkboolean(bool):
94 if IsBoolean(bool): return bool
95 return Boolean(bool)
97 class Type:
98 """An AE 4-char typename object"""
100 def __init__(self, type):
101 self.type = "%-4.4s" % str(type)
103 def __repr__(self):
104 return "Type(%s)" % `self.type`
106 def __str__(self):
107 return string.strip(self.type)
109 def __aepack__(self):
110 return pack(self.type, typeType)
112 def IsType(x):
113 return IsInstance(x, Type)
115 def mktype(type):
116 if IsType(type): return type
117 return Type(type)
120 class Keyword:
121 """An AE 4-char keyword object"""
123 def __init__(self, keyword):
124 self.keyword = "%-4.4s" % str(keyword)
126 def __repr__(self):
127 return "Keyword(%s)" % `self.keyword`
129 def __str__(self):
130 return string.strip(self.keyword)
132 def __aepack__(self):
133 return pack(self.keyword, typeKeyword)
135 def IsKeyword(x):
136 return IsInstance(x, Keyword)
138 class Range:
139 """An AE range object"""
141 def __init__(self, start, stop):
142 self.start = start
143 self.stop = stop
145 def __repr__(self):
146 return "Range(%s, %s)" % (`self.start`, `self.stop`)
148 def __str__(self):
149 return "%s thru %s" % (nice(self.start), nice(self.stop))
151 def __aepack__(self):
152 return pack({'star': self.start, 'stop': self.stop}, 'rang')
154 def IsRange(x):
155 return IsInstance(x, Range)
157 class Comparison:
158 """An AE Comparison"""
160 def __init__(self, obj1, relo, obj2):
161 self.obj1 = obj1
162 self.relo = "%-4.4s" % str(relo)
163 self.obj2 = obj2
165 def __repr__(self):
166 return "Comparison(%s, %s, %s)" % (`self.obj1`, `self.relo`, `self.obj2`)
168 def __str__(self):
169 return "%s %s %s" % (nice(self.obj1), string.strip(self.relo), nice(self.obj2))
171 def __aepack__(self):
172 return pack({'obj1': self.obj1,
173 'relo': mkenum(self.relo),
174 'obj2': self.obj2},
175 'cmpd')
177 def IsComparison(x):
178 return IsInstance(x, Comparison)
180 class NComparison(Comparison):
181 # The class attribute 'relo' must be set in a subclass
183 def __init__(self, obj1, obj2):
184 Comparison.__init__(obj1, self.relo, obj2)
186 class Ordinal:
187 """An AE Ordinal"""
189 def __init__(self, abso):
190 # self.obj1 = obj1
191 self.abso = "%-4.4s" % str(abso)
193 def __repr__(self):
194 return "Ordinal(%s)" % (`self.abso`)
196 def __str__(self):
197 return "%s" % (string.strip(self.abso))
199 def __aepack__(self):
200 return pack(self.abso, 'abso')
202 def IsOrdinal(x):
203 return IsInstance(x, Ordinal)
205 class NOrdinal(Ordinal):
206 # The class attribute 'abso' must be set in a subclass
208 def __init__(self):
209 Ordinal.__init__(self, self.abso)
211 class Logical:
212 """An AE logical expression object"""
214 def __init__(self, logc, term):
215 self.logc = "%-4.4s" % str(logc)
216 self.term = term
218 def __repr__(self):
219 return "Logical(%s, %s)" % (`self.logc`, `self.term`)
221 def __str__(self):
222 if type(self.term) == ListType and len(self.term) == 2:
223 return "%s %s %s" % (nice(self.term[0]),
224 string.strip(self.logc),
225 nice(self.term[1]))
226 else:
227 return "%s(%s)" % (string.strip(self.logc), nice(self.term))
229 def __aepack__(self):
230 return pack({'logc': mkenum(self.logc), 'term': self.term}, 'logi')
232 def IsLogical(x):
233 return IsInstance(x, Logical)
235 class StyledText:
236 """An AE object respresenting text in a certain style"""
238 def __init__(self, style, text):
239 self.style = style
240 self.text = text
242 def __repr__(self):
243 return "StyledText(%s, %s)" % (`self.style`, `self.text`)
245 def __str__(self):
246 return self.text
248 def __aepack__(self):
249 return pack({'ksty': self.style, 'ktxt': self.text}, 'STXT')
251 def IsStyledText(x):
252 return IsInstance(x, StyledText)
254 class AEText:
255 """An AE text object with style, script and language specified"""
257 def __init__(self, script, style, text):
258 self.script = script
259 self.style = style
260 self.text = text
262 def __repr__(self):
263 return "AEText(%s, %s, %s)" % (`self.script`, `self.style`, `self.text`)
265 def __str__(self):
266 return self.text
268 def __aepack__(self):
269 return pack({keyAEScriptTag: self.script, keyAEStyles: self.style,
270 keyAEText: self.text}, typeAEText)
272 def IsAEText(x):
273 return IsInstance(x, AEText)
275 class IntlText:
276 """A text object with script and language specified"""
278 def __init__(self, script, language, text):
279 self.script = script
280 self.language = language
281 self.text = text
283 def __repr__(self):
284 return "IntlText(%s, %s, %s)" % (`self.script`, `self.language`, `self.text`)
286 def __str__(self):
287 return self.text
289 def __aepack__(self):
290 return pack(struct.pack('hh', self.script, self.language)+self.text,
291 typeIntlText)
293 def IsIntlText(x):
294 return IsInstance(x, IntlText)
296 class IntlWritingCode:
297 """An object representing script and language"""
299 def __init__(self, script, language):
300 self.script = script
301 self.language = language
303 def __repr__(self):
304 return "IntlWritingCode(%s, %s)" % (`self.script`, `self.language`)
306 def __str__(self):
307 return "script system %d, language %d"%(self.script, self.language)
309 def __aepack__(self):
310 return pack(struct.pack('hh', self.script, self.language),
311 typeIntlWritingCode)
313 def IsIntlWritingCode(x):
314 return IsInstance(x, IntlWritingCode)
316 class QDPoint:
317 """A point"""
319 def __init__(self, v, h):
320 self.v = v
321 self.h = h
323 def __repr__(self):
324 return "QDPoint(%s, %s)" % (`self.v`, `self.h`)
326 def __str__(self):
327 return "(%d, %d)"%(self.v, self.h)
329 def __aepack__(self):
330 return pack(struct.pack('hh', self.v, self.h),
331 typeQDPoint)
333 def IsQDPoint(x):
334 return IsInstance(x, QDPoint)
336 class QDRectangle:
337 """A rectangle"""
339 def __init__(self, v0, h0, v1, h1):
340 self.v0 = v0
341 self.h0 = h0
342 self.v1 = v1
343 self.h1 = h1
345 def __repr__(self):
346 return "QDRectangle(%s, %s, %s, %s)" % (`self.v0`, `self.h0`,
347 `self.v1`, `self.h1`)
349 def __str__(self):
350 return "(%d, %d)-(%d, %d)"%(self.v0, self.h0, self.v1, self.h1)
352 def __aepack__(self):
353 return pack(struct.pack('hhhh', self.v0, self.h0, self.v1, self.h1),
354 typeQDRectangle)
356 def IsQDRectangle(x):
357 return IsInstance(x, QDRectangle)
359 class RGBColor:
360 """An RGB color"""
362 def __init__(self, r, g, b):
363 self.r = r
364 self.g = g
365 self.b = b
367 def __repr__(self):
368 return "RGBColor(%s, %s, %s)" % (`self.r`, `self.g`, `self.b`)
370 def __str__(self):
371 return "0x%x red, 0x%x green, 0x%x blue"% (self.r, self.g, self.b)
373 def __aepack__(self):
374 return pack(struct.pack('hhh', self.r, self.g, self.b),
375 typeRGBColor)
377 def IsRGBColor(x):
378 return IsInstance(x, RGBColor)
380 class ObjectSpecifier:
382 """A class for constructing and manipulation AE object specifiers in python.
384 An object specifier is actually a record with four fields:
386 key type description
387 --- ---- -----------
389 'want' type 4-char class code of thing we want,
390 e.g. word, paragraph or property
392 'form' enum how we specify which 'want' thing(s) we want,
393 e.g. by index, by range, by name, or by property specifier
395 'seld' any which thing(s) we want,
396 e.g. its index, its name, or its property specifier
398 'from' object the object in which it is contained,
399 or null, meaning look for it in the application
401 Note that we don't call this class plain "Object", since that name
402 is likely to be used by the application.
405 def __init__(self, want, form, seld, fr = None):
406 self.want = want
407 self.form = form
408 self.seld = seld
409 self.fr = fr
411 def __repr__(self):
412 s = "ObjectSpecifier(%s, %s, %s" % (`self.want`, `self.form`, `self.seld`)
413 if self.fr:
414 s = s + ", %s)" % `self.fr`
415 else:
416 s = s + ")"
417 return s
419 def __aepack__(self):
420 return pack({'want': mktype(self.want),
421 'form': mkenum(self.form),
422 'seld': self.seld,
423 'from': self.fr},
424 'obj ')
426 def IsObjectSpecifier(x):
427 return IsInstance(x, ObjectSpecifier)
430 # Backwards compatability, sigh...
431 class Property(ObjectSpecifier):
433 def __init__(self, which, fr = None, want='prop'):
434 ObjectSpecifier.__init__(self, want, 'prop', mktype(which), fr)
436 def __repr__(self):
437 if self.fr:
438 return "Property(%s, %s)" % (`self.seld.type`, `self.fr`)
439 else:
440 return "Property(%s)" % `self.seld.type`
442 def __str__(self):
443 if self.fr:
444 return "Property %s of %s" % (str(self.seld), str(self.fr))
445 else:
446 return "Property %s" % str(self.seld)
449 class NProperty(ObjectSpecifier):
450 # Subclasses *must* self baseclass attributes:
451 # want is the type of this property
452 # which is the property name of this property
454 def __init__(self, fr = None):
455 #try:
456 # dummy = self.want
457 #except:
458 # self.want = 'prop'
459 self.want = 'prop'
460 ObjectSpecifier.__init__(self, self.want, 'prop',
461 mktype(self.which), fr)
463 def __repr__(self):
464 rv = "Property(%s"%`self.seld.type`
465 if self.fr:
466 rv = rv + ", fr=%s" % `self.fr`
467 if self.want != 'prop':
468 rv = rv + ", want=%s" % `self.want`
469 return rv + ")"
471 def __str__(self):
472 if self.fr:
473 return "Property %s of %s" % (str(self.seld), str(self.fr))
474 else:
475 return "Property %s" % str(self.seld)
478 class SelectableItem(ObjectSpecifier):
480 def __init__(self, want, seld, fr = None):
481 t = type(seld)
482 if t == StringType:
483 form = 'name'
484 elif IsRange(seld):
485 form = 'rang'
486 elif IsComparison(seld) or IsLogical(seld):
487 form = 'test'
488 elif t == TupleType:
489 # Breakout: specify both form and seld in a tuple
490 # (if you want ID or rele or somesuch)
491 form, seld = seld
492 else:
493 form = 'indx'
494 ObjectSpecifier.__init__(self, want, form, seld, fr)
497 class ComponentItem(SelectableItem):
498 # Derived classes *must* set the *class attribute* 'want' to some constant
499 # Also, dictionaries _propdict and _elemdict must be set to map property
500 # and element names to the correct classes
502 def __init__(self, which, fr = None):
503 SelectableItem.__init__(self, self.want, which, fr)
505 def __repr__(self):
506 if not self.fr:
507 return "%s(%s)" % (self.__class__.__name__, `self.seld`)
508 return "%s(%s, %s)" % (self.__class__.__name__, `self.seld`, `self.fr`)
510 def __str__(self):
511 seld = self.seld
512 if type(seld) == StringType:
513 ss = repr(seld)
514 elif IsRange(seld):
515 start, stop = seld.start, seld.stop
516 if type(start) == InstanceType == type(stop) and \
517 start.__class__ == self.__class__ == stop.__class__:
518 ss = str(start.seld) + " thru " + str(stop.seld)
519 else:
520 ss = str(seld)
521 else:
522 ss = str(seld)
523 s = "%s %s" % (self.__class__.__name__, ss)
524 if self.fr: s = s + " of %s" % str(self.fr)
525 return s
527 def __getattr__(self, name):
528 if self._elemdict.has_key(name):
529 cls = self._elemdict[name]
530 return DelayedComponentItem(cls, self)
531 if self._propdict.has_key(name):
532 cls = self._propdict[name]
533 return cls(self)
534 raise AttributeError, name
537 class DelayedComponentItem:
538 def __init__(self, compclass, fr):
539 self.compclass = compclass
540 self.fr = fr
542 def __call__(self, which):
543 return self.compclass(which, self.fr)
545 def __repr__(self):
546 return "%s(???, %s)" % (self.__class__.__name__, `self.fr`)
548 def __str__(self):
549 return "selector for element %s of %s"%(self.__class__.__name__, str(self.fr))
551 template = """
552 class %s(ComponentItem): want = '%s'
555 exec template % ("Text", 'text')
556 exec template % ("Character", 'cha ')
557 exec template % ("Word", 'cwor')
558 exec template % ("Line", 'clin')
559 exec template % ("paragraph", 'cpar')
560 exec template % ("Window", 'cwin')
561 exec template % ("Document", 'docu')
562 exec template % ("File", 'file')
563 exec template % ("InsertionPoint", 'cins')