Fix an amazing number of typos & malformed sentences reported by Detlef
[python/dscho.git] / Mac / Lib / lib-toolbox / aetypes.py
bloba4840c5d65714f60cd595d025b8db65df3363f90
1 """aetypes - Python objects representing various AE types."""
3 from AppleEvents import *
4 from AERegistry import *
5 from AEObjects import *
6 import struct
7 from types import *
8 import string
11 # convoluted, since there are cyclic dependencies between this file and
12 # aetools_convert.
14 def pack(*args):
15 from aepack import pack
16 return apply(pack, args)
18 def IsSubclass(cls, base):
19 """Test whether CLASS1 is the same as or a subclass of CLASS2"""
20 # Loop to optimize for single inheritance
21 while 1:
22 if cls is base: return 1
23 if len(cls.__bases__) <> 1: break
24 cls = cls.__bases__[0]
25 # Recurse to cope with multiple inheritance
26 for c in cls.__bases__:
27 if IsSubclass(c, base): return 1
28 return 0
30 def IsInstance(x, cls):
31 """Test whether OBJECT is an instance of (a subclass of) CLASS"""
32 return type(x) is InstanceType and IsSubclass(x.__class__, cls)
34 def nice(s):
35 """'nice' representation of an object"""
36 if type(s) is StringType: return repr(s)
37 else: return str(s)
39 class Unknown:
40 """An uninterpreted AE object"""
42 def __init__(self, type, data):
43 self.type = type
44 self.data = data
46 def __repr__(self):
47 return "Unknown(%s, %s)" % (`self.type`, `self.data`)
49 def __aepack__(self):
50 return pack(self.data, self.type)
52 class Enum:
53 """An AE enumeration value"""
55 def __init__(self, enum):
56 self.enum = "%-4.4s" % str(enum)
58 def __repr__(self):
59 return "Enum(%s)" % `self.enum`
61 def __str__(self):
62 return string.strip(self.enum)
64 def __aepack__(self):
65 return pack(self.enum, typeEnumeration)
67 def IsEnum(x):
68 return IsInstance(x, Enum)
70 def mkenum(enum):
71 if IsEnum(enum): return enum
72 return Enum(enum)
74 class Boolean:
75 """An AE boolean value"""
77 def __init__(self, bool):
78 self.bool = (not not bool)
80 def __repr__(self):
81 return "Boolean(%s)" % `self.bool`
83 def __str__(self):
84 if self.bool:
85 return "True"
86 else:
87 return "False"
89 def __aepack__(self):
90 return pack(struct.pack('b', self.bool), 'bool')
92 def IsBoolean(x):
93 return IsInstance(x, Boolean)
95 def mkboolean(bool):
96 if IsBoolean(bool): return bool
97 return Boolean(bool)
99 class Type:
100 """An AE 4-char typename object"""
102 def __init__(self, type):
103 self.type = "%-4.4s" % str(type)
105 def __repr__(self):
106 return "Type(%s)" % `self.type`
108 def __str__(self):
109 return string.strip(self.type)
111 def __aepack__(self):
112 return pack(self.type, typeType)
114 def IsType(x):
115 return IsInstance(x, Type)
117 def mktype(type):
118 if IsType(type): return type
119 return Type(type)
122 class Keyword:
123 """An AE 4-char keyword object"""
125 def __init__(self, keyword):
126 self.keyword = "%-4.4s" % str(keyword)
128 def __repr__(self):
129 return "Keyword(%s)" % `self.keyword`
131 def __str__(self):
132 return string.strip(self.keyword)
134 def __aepack__(self):
135 return pack(self.keyword, typeKeyword)
137 def IsKeyword(x):
138 return IsInstance(x, Keyword)
140 class Range:
141 """An AE range object"""
143 def __init__(self, start, stop):
144 self.start = start
145 self.stop = stop
147 def __repr__(self):
148 return "Range(%s, %s)" % (`self.start`, `self.stop`)
150 def __str__(self):
151 return "%s thru %s" % (nice(self.start), nice(self.stop))
153 def __aepack__(self):
154 return pack({'star': self.start, 'stop': self.stop}, 'rang')
156 def IsRange(x):
157 return IsInstance(x, Range)
159 class Comparison:
160 """An AE Comparison"""
162 def __init__(self, obj1, relo, obj2):
163 self.obj1 = obj1
164 self.relo = "%-4.4s" % str(relo)
165 self.obj2 = obj2
167 def __repr__(self):
168 return "Comparison(%s, %s, %s)" % (`self.obj1`, `self.relo`, `self.obj2`)
170 def __str__(self):
171 return "%s %s %s" % (nice(self.obj1), string.strip(self.relo), nice(self.obj2))
173 def __aepack__(self):
174 return pack({'obj1': self.obj1,
175 'relo': mkenum(self.relo),
176 'obj2': self.obj2},
177 'cmpd')
179 def IsComparison(x):
180 return IsInstance(x, Comparison)
182 class NComparison(Comparison):
183 # The class attribute 'relo' must be set in a subclass
185 def __init__(self, obj1, obj2):
186 Comparison.__init__(obj1, self.relo, obj2)
188 class Ordinal:
189 """An AE Ordinal"""
191 def __init__(self, abso):
192 # self.obj1 = obj1
193 self.abso = "%-4.4s" % str(abso)
195 def __repr__(self):
196 return "Ordinal(%s)" % (`self.abso`)
198 def __str__(self):
199 return "%s" % (string.strip(self.abso))
201 def __aepack__(self):
202 return pack(self.abso, 'abso')
204 def IsOrdinal(x):
205 return IsInstance(x, Ordinal)
207 class NOrdinal(Ordinal):
208 # The class attribute 'abso' must be set in a subclass
210 def __init__(self):
211 Ordinal.__init__(self, self.abso)
213 class Logical:
214 """An AE logical expression object"""
216 def __init__(self, logc, term):
217 self.logc = "%-4.4s" % str(logc)
218 self.term = term
220 def __repr__(self):
221 return "Logical(%s, %s)" % (`self.logc`, `self.term`)
223 def __str__(self):
224 if type(self.term) == ListType and len(self.term) == 2:
225 return "%s %s %s" % (nice(self.term[0]),
226 string.strip(self.logc),
227 nice(self.term[1]))
228 else:
229 return "%s(%s)" % (string.strip(self.logc), nice(self.term))
231 def __aepack__(self):
232 return pack({'logc': mkenum(self.logc), 'term': self.term}, 'logi')
234 def IsLogical(x):
235 return IsInstance(x, Logical)
237 class StyledText:
238 """An AE object respresenting text in a certain style"""
240 def __init__(self, style, text):
241 self.style = style
242 self.text = text
244 def __repr__(self):
245 return "StyledText(%s, %s)" % (`self.style`, `self.text`)
247 def __str__(self):
248 return self.text
250 def __aepack__(self):
251 return pack({'ksty': self.style, 'ktxt': self.text}, 'STXT')
253 def IsStyledText(x):
254 return IsInstance(x, StyledText)
256 class AEText:
257 """An AE text object with style, script and language specified"""
259 def __init__(self, script, style, text):
260 self.script = script
261 self.style = style
262 self.text = text
264 def __repr__(self):
265 return "AEText(%s, %s, %s)" % (`self.script`, `self.style`, `self.text`)
267 def __str__(self):
268 return self.text
270 def __aepack__(self):
271 return pack({keyAEScriptTag: self.script, keyAEStyles: self.style,
272 keyAEText: self.text}, typeAEText)
274 def IsAEText(x):
275 return IsInstance(x, AEText)
277 class IntlText:
278 """A text object with script and language specified"""
280 def __init__(self, script, language, text):
281 self.script = script
282 self.language = language
283 self.text = text
285 def __repr__(self):
286 return "IntlText(%s, %s, %s)" % (`self.script`, `self.language`, `self.text`)
288 def __str__(self):
289 return self.text
291 def __aepack__(self):
292 return pack(struct.pack('hh', self.script, self.language)+self.text,
293 typeIntlText)
295 def IsIntlText(x):
296 return IsInstance(x, IntlText)
298 class IntlWritingCode:
299 """An object representing script and language"""
301 def __init__(self, script, language):
302 self.script = script
303 self.language = language
305 def __repr__(self):
306 return "IntlWritingCode(%s, %s)" % (`self.script`, `self.language`)
308 def __str__(self):
309 return "script system %d, language %d"%(self.script, self.language)
311 def __aepack__(self):
312 return pack(struct.pack('hh', self.script, self.language),
313 typeIntlWritingCode)
315 def IsIntlWritingCode(x):
316 return IsInstance(x, IntlWritingCode)
318 class QDPoint:
319 """A point"""
321 def __init__(self, v, h):
322 self.v = v
323 self.h = h
325 def __repr__(self):
326 return "QDPoint(%s, %s)" % (`self.v`, `self.h`)
328 def __str__(self):
329 return "(%d, %d)"%(self.v, self.h)
331 def __aepack__(self):
332 return pack(struct.pack('hh', self.v, self.h),
333 typeQDPoint)
335 def IsQDPoint(x):
336 return IsInstance(x, QDPoint)
338 class QDRectangle:
339 """A rectangle"""
341 def __init__(self, v0, h0, v1, h1):
342 self.v0 = v0
343 self.h0 = h0
344 self.v1 = v1
345 self.h1 = h1
347 def __repr__(self):
348 return "QDRectangle(%s, %s, %s, %s)" % (`self.v0`, `self.h0`,
349 `self.v1`, `self.h1`)
351 def __str__(self):
352 return "(%d, %d)-(%d, %d)"%(self.v0, self.h0, self.v1, self.h1)
354 def __aepack__(self):
355 return pack(struct.pack('hhhh', self.v0, self.h0, self.v1, self.h1),
356 typeQDRectangle)
358 def IsQDRectangle(x):
359 return IsInstance(x, QDRectangle)
361 class RGBColor:
362 """An RGB color"""
364 def __init__(self, r, g, b):
365 self.r = r
366 self.g = g
367 self.b = b
369 def __repr__(self):
370 return "RGBColor(%s, %s, %s)" % (`self.r`, `self.g`, `self.b`)
372 def __str__(self):
373 return "0x%x red, 0x%x green, 0x%x blue"% (self.r, self.g, self.b)
375 def __aepack__(self):
376 return pack(struct.pack('hhh', self.r, self.g, self.b),
377 typeRGBColor)
379 def IsRGBColor(x):
380 return IsInstance(x, RGBColor)
382 class ObjectSpecifier:
384 """A class for constructing and manipulation AE object specifiers in python.
386 An object specifier is actually a record with four fields:
388 key type description
389 --- ---- -----------
391 'want' type 4-char class code of thing we want,
392 e.g. word, paragraph or property
394 'form' enum how we specify which 'want' thing(s) we want,
395 e.g. by index, by range, by name, or by property specifier
397 'seld' any which thing(s) we want,
398 e.g. its index, its name, or its property specifier
400 'from' object the object in which it is contained,
401 or null, meaning look for it in the application
403 Note that we don't call this class plain "Object", since that name
404 is likely to be used by the application.
407 def __init__(self, want, form, seld, fr = None):
408 self.want = want
409 self.form = form
410 self.seld = seld
411 self.fr = fr
413 def __repr__(self):
414 s = "ObjectSpecifier(%s, %s, %s" % (`self.want`, `self.form`, `self.seld`)
415 if self.fr:
416 s = s + ", %s)" % `self.fr`
417 else:
418 s = s + ")"
419 return s
421 def __aepack__(self):
422 return pack({'want': mktype(self.want),
423 'form': mkenum(self.form),
424 'seld': self.seld,
425 'from': self.fr},
426 'obj ')
428 def IsObjectSpecifier(x):
429 return IsInstance(x, ObjectSpecifier)
432 # Backwards compatability, sigh...
433 class Property(ObjectSpecifier):
435 def __init__(self, which, fr = None, want='prop'):
436 ObjectSpecifier.__init__(self, want, 'prop', mktype(which), fr)
438 def __repr__(self):
439 if self.fr:
440 return "Property(%s, %s)" % (`self.seld.type`, `self.fr`)
441 else:
442 return "Property(%s)" % `self.seld.type`
444 def __str__(self):
445 if self.fr:
446 return "Property %s of %s" % (str(self.seld), str(self.fr))
447 else:
448 return "Property %s" % str(self.seld)
451 class NProperty(ObjectSpecifier):
452 # Subclasses *must* self baseclass attributes:
453 # want is the type of this property
454 # which is the property name of this property
456 def __init__(self, fr = None):
457 #try:
458 # dummy = self.want
459 #except:
460 # self.want = 'prop'
461 self.want = 'prop'
462 ObjectSpecifier.__init__(self, self.want, 'prop',
463 mktype(self.which), fr)
465 def __repr__(self):
466 rv = "Property(%s"%`self.seld.type`
467 if self.fr:
468 rv = rv + ", fr=%s" % `self.fr`
469 if self.want != 'prop':
470 rv = rv + ", want=%s" % `self.want`
471 return rv + ")"
473 def __str__(self):
474 if self.fr:
475 return "Property %s of %s" % (str(self.seld), str(self.fr))
476 else:
477 return "Property %s" % str(self.seld)
480 class SelectableItem(ObjectSpecifier):
482 def __init__(self, want, seld, fr = None):
483 t = type(seld)
484 if t == StringType:
485 form = 'name'
486 elif IsRange(seld):
487 form = 'rang'
488 elif IsComparison(seld) or IsLogical(seld):
489 form = 'test'
490 elif t == TupleType:
491 # Breakout: specify both form and seld in a tuple
492 # (if you want ID or rele or somesuch)
493 form, seld = seld
494 else:
495 form = 'indx'
496 ObjectSpecifier.__init__(self, want, form, seld, fr)
499 class ComponentItem(SelectableItem):
500 # Derived classes *must* set the *class attribute* 'want' to some constant
501 # Also, dictionaries _propdict and _elemdict must be set to map property
502 # and element names to the correct classes
504 def __init__(self, which, fr = None):
505 SelectableItem.__init__(self, self.want, which, fr)
507 def __repr__(self):
508 if not self.fr:
509 return "%s(%s)" % (self.__class__.__name__, `self.seld`)
510 return "%s(%s, %s)" % (self.__class__.__name__, `self.seld`, `self.fr`)
512 def __str__(self):
513 seld = self.seld
514 if type(seld) == StringType:
515 ss = repr(seld)
516 elif IsRange(seld):
517 start, stop = seld.start, seld.stop
518 if type(start) == InstanceType == type(stop) and \
519 start.__class__ == self.__class__ == stop.__class__:
520 ss = str(start.seld) + " thru " + str(stop.seld)
521 else:
522 ss = str(seld)
523 else:
524 ss = str(seld)
525 s = "%s %s" % (self.__class__.__name__, ss)
526 if self.fr: s = s + " of %s" % str(self.fr)
527 return s
529 def __getattr__(self, name):
530 if self._elemdict.has_key(name):
531 cls = self._elemdict[name]
532 return DelayedComponentItem(cls, self)
533 if self._propdict.has_key(name):
534 cls = self._propdict[name]
535 return cls(self)
536 raise AttributeError, name
539 class DelayedComponentItem:
540 def __init__(self, compclass, fr):
541 self.compclass = compclass
542 self.fr = fr
544 def __call__(self, which):
545 return self.compclass(which, self.fr)
547 def __repr__(self):
548 return "%s(???, %s)" % (self.__class__.__name__, `self.fr`)
550 def __str__(self):
551 return "selector for element %s of %s"%(self.__class__.__name__, str(self.fr))
553 template = """
554 class %s(ComponentItem): want = '%s'
557 exec template % ("Text", 'text')
558 exec template % ("Character", 'cha ')
559 exec template % ("Word", 'cwor')
560 exec template % ("Line", 'clin')
561 exec template % ("paragraph", 'cpar')
562 exec template % ("Window", 'cwin')
563 exec template % ("Document", 'docu')
564 exec template % ("File", 'file')
565 exec template % ("InsertionPoint", 'cins')