Fix the HTML tarball target to generate the HTML if needed instead of
[python/dscho.git] / Mac / Contrib / PythonScript / baetypes.py
blobb0875482f3b18de5985b22fe6adc48cf320f8f56
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 # print enum
72 if IsEnum(enum): return enum
73 return Enum(enum)
75 class Boolean:
76 """An AE boolean value"""
78 def __init__(self, bool):
79 if bool:
80 self.bool = "%-4.4s" % str(typeTrue)
81 else:
82 self.bool = "%-4.4s" % str(typeFalse)
84 def __repr__(self):
85 return "Boolean(%s)" % self.bool
87 def __str__(self):
88 return self.bool
90 def __aepack__(self):
91 if self.bool == 'true':
92 return pack('', typeTrue)
93 else:
94 return pack('', typeFalse)
96 def IsBoolean(x):
97 return IsInstance(x, Boolean)
99 def mkboolean(bool):
100 # print bool
101 if IsBoolean(bool): return bool
102 return Boolean(bool)
104 class Type:
105 """An AE 4-char typename object"""
107 def __init__(self, _type):
108 self.type = "%-4.4s" % str(_type)
110 def __repr__(self):
111 return "Type(%s)" % `self.type`
113 def __str__(self):
114 return string.strip(self.type)
116 def __aepack__(self):
117 # print self.type, typeType
118 return pack(self.type, typeType)
120 def IsType(x):
121 return IsInstance(x, Type)
123 def mktype(_type):
124 # Should check for apple ID codes, will allow
125 if IsType(_type): return _type
126 if type(_type) <> StringType: return _type
127 if len(_type) <> 4: return Type(eval('type' + _type))
128 return Type(_type)
131 class Keyword:
132 """An AE 4-char keyword object"""
134 def __init__(self, keyword):
135 self.keyword = "%-4.4s" % str(keyword)
137 def __repr__(self):
138 return "Keyword(%s)" % `self.keyword`
140 def __str__(self):
141 return string.strip(self.keyword)
143 def __aepack__(self):
144 return pack(self.keyword, typeKeyword)
146 def IsKeyword(x):
147 return IsInstance(x, Keyword)
149 class Range:
150 """An AE range object"""
152 def __init__(self, start, stop):
153 self.start = start
154 self.stop = stop
156 def __repr__(self):
157 return "Range(%s, %s)" % (`self.start`, `self.stop`)
159 def __str__(self):
160 return "%s thru %s" % (nice(self.start), nice(self.stop))
162 def __aepack__(self):
163 return pack({'star': self.start, 'stop': self.stop}, 'rang')
165 def IsRange(x):
166 return IsInstance(x, Range)
168 class Comparison:
169 """An AE Comparison"""
171 def __init__(self, obj1, relo, obj2):
172 self.obj1 = obj1
173 self.relo = "%-4.4s" % str(relo)
174 self.obj2 = obj2
176 def __repr__(self):
177 return "Comparison(%s, %s, %s)" % (`self.obj1`, `self.relo`, `self.obj2`)
179 def __str__(self):
180 return "%s %s %s" % (nice(self.obj1), string.strip(self.relo), nice(self.obj2))
182 def __aepack__(self):
183 return pack({'obj1': self.obj1,
184 'relo': mkenum(self.relo),
185 'obj2': self.obj2},
186 'cmpd')
188 def IsComparison(x):
189 return IsInstance(x, Comparison)
191 class NComparison(Comparison):
192 # The class attribute 'relo' must be set in a subclass
194 def __init__(self, obj1, obj2):
195 Comparison.__init__(obj1, self.relo, obj2)
197 class Ordinal:
198 """An AE Ordinal"""
200 def __init__(self, ord):
201 self.ord = ord
203 def __repr__(self):
204 return "baetypes.Ordinal(%s)" % `self.ord`
206 def __str__(self):
207 return "%s" % (string.strip(self.ord))
209 def __aepack__(self):
210 return pack(self.ord, typeAbsoluteOrdinal)
212 def IsOrdinal(x):
213 # print 'IsOrdinal', x, IsInstance(x, Ordinal)
214 return IsInstance(x, Ordinal)
216 def mkOrdinal(Ord):
217 if IsOrdinal(Ord): return Ord
218 return Ordinal(Ord)
222 class NOrdinal(Ordinal):
223 # The class attribute 'abso' must be set in a subclass
225 def __init__(self ):
226 # print 'NOrdinal', self.abso
227 Ordinal.__init__(self, self.abso)
229 class Logical:
230 """An AE logical expression object"""
232 def __init__(self, logc, term):
233 self.logc = "%-4.4s" % str(logc)
234 self.term = term
236 def __repr__(self):
237 return "Logical(%s, %s)" % (`self.logc`, `self.term`)
239 def __str__(self):
240 if type(self.term) == ListType and len(self.term) == 2:
241 return "%s %s %s" % (nice(self.term[0]),
242 string.strip(self.logc),
243 nice(self.term[1]))
244 else:
245 return "%s(%s)" % (string.strip(self.logc), nice(self.term))
247 def __aepack__(self):
248 return pack({'logc': mkenum(self.logc), 'term': self.term}, 'logi')
250 def IsLogical(x):
251 return IsInstance(x, Logical)
253 class StyledText:
254 """An AE object respresenting text in a certain style"""
256 def __init__(self, style, text):
257 self.style = style
258 self.text = text
260 def __repr__(self):
261 return "StyledText(%s, %s)" % (`self.style`, `self.text`)
263 def __str__(self):
264 return self.text
266 def __aepack__(self):
267 return pack({'ksty': self.style, 'ktxt': self.text}, 'STXT')
269 def IsStyledText(x):
270 return IsInstance(x, StyledText)
272 class AEText:
273 """An AE text object with style, script and language specified"""
275 def __init__(self, script, style, text):
276 self.script = script
277 self.style = style
278 self.text = text
280 def __repr__(self):
281 return "AEText(%s, %s, %s)" % (`self.script`, `self.style`, `self.text`)
283 def __str__(self):
284 return self.text
286 def __aepack__(self):
287 return pack({keyAEScriptTag: self.script, keyAEStyles: self.style,
288 keyAEText: self.text}, typeAEText)
290 def IsAEText(x):
291 return IsInstance(x, AEText)
293 class IntlText:
294 """A text object with script and language specified"""
296 def __init__(self, script, language, text):
297 self.script = script
298 self.language = language
299 self.text = text
301 def __repr__(self):
302 return "IntlText(%s, %s, %s)" % (`self.script`, `self.language`, `self.text`)
304 def __str__(self):
305 return self.text
307 def __aepack__(self):
308 return pack(struct.pack('hh', self.script, self.language)+self.text,
309 typeIntlText)
311 def IsIntlText(x):
312 return IsInstance(x, IntlText)
314 class IntlWritingCode:
315 """An object representing script and language"""
317 def __init__(self, script, language):
318 self.script = script
319 self.language = language
321 def __repr__(self):
322 return "IntlWritingCode(%s, %s)" % (`self.script`, `self.language`)
324 def __str__(self):
325 return "script system %d, language %d"%(self.script, self.language)
327 def __aepack__(self):
328 return pack(struct.pack('hh', self.script, self.language),
329 typeIntlWritingCode)
331 def IsIntlWritingCode(x):
332 return IsInstance(x, IntlWritingCode)
334 class QDPoint:
335 """A point"""
337 def __init__(self, v, h):
338 self.v = v
339 self.h = h
341 def __repr__(self):
342 return "QDPoint(%s, %s)" % (`self.v`, `self.h`)
344 def __str__(self):
345 return "(%d, %d)"%(self.v, self.h)
347 def __aepack__(self):
348 return pack(struct.pack('hh', self.v, self.h),
349 typeQDPoint)
351 def IsQDPoint(x):
352 return IsInstance(x, QDPoint)
354 class QDRectangle:
355 """A rectangle"""
357 def __init__(self, v0, h0, v1, h1):
358 self.v0 = v0
359 self.h0 = h0
360 self.v1 = v1
361 self.h1 = h1
363 def __repr__(self):
364 return "QDRectangle(%s, %s, %s, %s)" % (`self.v0`, `self.h0`,
365 `self.v1`, `self.h1`)
367 def __str__(self):
368 return "(%d, %d)-(%d, %d)"%(self.v0, self.h0, self.v1, self.h1)
370 def __aepack__(self):
371 return pack(struct.pack('hhhh', self.v0, self.h0, self.v1, self.h1),
372 typeQDRectangle)
374 def IsQDRectangle(x):
375 return IsInstance(x, QDRectangle)
377 class RGBColor:
378 """An RGB color"""
380 def __init__(self, r, g, b):
381 self.r = r
382 self.g = g
383 self.b = b
385 def __repr__(self):
386 return "RGBColor(%s, %s, %s)" % (`self.r`, `self.g`, `self.b`)
388 def __str__(self):
389 return "0x%x red, 0x%x green, 0x%x blue"% (self.r, self.g, self.b)
391 def __aepack__(self):
392 return pack(struct.pack('hhh', self.r, self.g, self.b),
393 typeRGBColor)
395 def IsRGBColor(x):
396 return IsInstance(x, RGBColor)
398 class ObjectSpecifier:
400 """A class for constructing and manipulation AE object specifiers in python.
402 An object specifier is actually a record with four fields:
404 key type description
405 --- ---- -----------
407 'want' type 4-char class code of thing we want,
408 e.g. word, paragraph or property
410 'form' enum how we specify which 'want' thing(s) we want,
411 e.g. by index, by range, by name, or by property specifier
413 'seld' any which thing(s) we want,
414 e.g. its index, its name, or its property specifier
416 'from' object the object in which it is contained,
417 or null, meaning look for it in the application
419 Note that we don't call this class plain "Object", since that name
420 is likely to be used by the application.
423 def __init__(self, want, form, seld, fr = None):
424 self.want = want
425 self.form = form
426 self.seld = seld
427 self.fr = fr
429 def __repr__(self):
430 s = "ObjectSpecifier(%s, %s, %s" % (`self.want`, `self.form`, `self.seld`)
431 if self.fr:
432 s = s + ", %s)" % `self.fr`
433 else:
434 s = s + ")"
435 return s
437 def __aepack__(self):
438 return pack({'want': mktype(self.want),
439 'form': mkenum(self.form),
440 'seld': self.seld,
441 'from': self.fr},
442 'obj ')
444 def IsObjectSpecifier(x):
445 return IsInstance(x, ObjectSpecifier)
448 # Backwards compatability, sigh...
449 class Property(ObjectSpecifier):
451 def __init__(self, which, fr = None, want='prop'):
452 ObjectSpecifier.__init__(self, want, 'prop', mktype(which), fr)
454 def __repr__(self):
455 if self.fr:
456 return "Property_r(%s, %s)" % (`self.seld.type`, `self.fr`)
457 else:
458 return "Property_r(%s)" % `self.seld.type`
460 def __str__(self):
461 if self.fr:
462 return "Property %s of %s" % (str(self.seld), str(self.fr))
463 else:
464 return "Property_s %s" % str(self.seld)
467 class NProperty(ObjectSpecifier):
468 # Subclasses *must* self baseclass attributes:
469 # want is the type of this property
470 # which is the property name of this property
472 def __init__(self, want, form, seld, fr = None):
473 ObjectSpecifier.__init__(self, want, form,
474 mktype(seld), fr)
477 class SelectableItem(ObjectSpecifier):
479 def __init__(self, want, seld, fr = None):
480 t = type(seld)
481 if t == StringType:
482 form = 'name'
483 elif IsRange(seld):
484 form = 'rang'
485 elif IsComparison(seld) or IsLogical(seld):
486 form = 'test'
487 elif t == TupleType:
488 # Breakout: specify both form and seld in a tuple
489 # (if you want ID or rele or somesuch)
490 form, seld = seld
491 else:
492 form = 'indx'
493 ObjectSpecifier.__init__(self, want, form, seld, fr)
496 class ComponentItem(SelectableItem):
497 # Derived classes *must* set the *class attribute* 'want' to some constant
498 # Also, dictionaries _propdict and _elemdict must be set to map property
499 # and element names to the correct classes
501 def __init__(self, want, which, fr = None):
502 SelectableItem.__init__(self, want, which, fr)
504 def __repr__(self):
505 if not self.fr:
506 return "%s(%s)" % (self.__class__.__name__, `self.seld`)
507 return "%s(%s, %s)" % (self.__class__.__name__, `self.seld`, `self.fr`)
509 def __str__(self):
510 seld = self.seld
511 if type(seld) == StringType:
512 ss = repr(seld)
513 elif IsRange(seld):
514 start, stop = seld.start, seld.stop
515 if type(start) == InstanceType == type(stop) and \
516 start.__class__ == self.__class__ == stop.__class__:
517 ss = str(start.seld) + " thru " + str(stop.seld)
518 else:
519 ss = str(seld)
520 else:
521 ss = str(seld)
522 s = "%s %s" % (self.__class__.__name__, ss)
523 if self.fr: s = s + " of %s" % str(self.fr)
524 return s
526 # def __getattr__(self, name):
527 # print 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')