1 """aetypes - Python objects representing various AE types."""
3 from Carbon
.AppleEvents
import *
9 # convoluted, since there are cyclic dependencies between this file and
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
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
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
)
33 """'nice' representation of an object"""
34 if type(s
) is StringType
: return repr(s
)
38 """An uninterpreted AE object"""
40 def __init__(self
, type, data
):
45 return "Unknown(%s, %s)" % (`self
.type`
, `self
.data`
)
48 return pack(self
.data
, self
.type)
51 """An AE enumeration value"""
53 def __init__(self
, enum
):
54 self
.enum
= "%-4.4s" % str(enum
)
57 return "Enum(%s)" % `self
.enum`
60 return string
.strip(self
.enum
)
63 return pack(self
.enum
, typeEnumeration
)
66 return IsInstance(x
, Enum
)
69 if IsEnum(enum
): return enum
73 """An AE boolean value"""
75 def __init__(self
, bool):
76 self
.bool = (not not bool)
79 return "Boolean(%s)" % `self
.bool`
88 return pack(struct
.pack('b', self
.bool), 'bool')
91 return IsInstance(x
, Boolean
)
94 if IsBoolean(bool): return bool
98 """An AE 4-char typename object"""
100 def __init__(self
, type):
101 self
.type = "%-4.4s" % str(type)
104 return "Type(%s)" % `self
.type`
107 return string
.strip(self
.type)
109 def __aepack__(self
):
110 return pack(self
.type, typeType
)
113 return IsInstance(x
, Type
)
116 if IsType(type): return type
121 """An AE 4-char keyword object"""
123 def __init__(self
, keyword
):
124 self
.keyword
= "%-4.4s" % str(keyword
)
127 return "Keyword(%s)" % `self
.keyword`
130 return string
.strip(self
.keyword
)
132 def __aepack__(self
):
133 return pack(self
.keyword
, typeKeyword
)
136 return IsInstance(x
, Keyword
)
139 """An AE range object"""
141 def __init__(self
, start
, stop
):
146 return "Range(%s, %s)" % (`self
.start`
, `self
.stop`
)
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')
155 return IsInstance(x
, Range
)
158 """An AE Comparison"""
160 def __init__(self
, obj1
, relo
, obj2
):
162 self
.relo
= "%-4.4s" % str(relo
)
166 return "Comparison(%s, %s, %s)" % (`self
.obj1`
, `self
.relo`
, `self
.obj2`
)
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
),
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
)
189 def __init__(self
, abso
):
191 self
.abso
= "%-4.4s" % str(abso
)
194 return "Ordinal(%s)" % (`self
.abso`
)
197 return "%s" % (string
.strip(self
.abso
))
199 def __aepack__(self
):
200 return pack(self
.abso
, 'abso')
203 return IsInstance(x
, Ordinal
)
205 class NOrdinal(Ordinal
):
206 # The class attribute 'abso' must be set in a subclass
209 Ordinal
.__init
__(self
, self
.abso
)
212 """An AE logical expression object"""
214 def __init__(self
, logc
, term
):
215 self
.logc
= "%-4.4s" % str(logc
)
219 return "Logical(%s, %s)" % (`self
.logc`
, `self
.term`
)
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
),
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')
233 return IsInstance(x
, Logical
)
236 """An AE object respresenting text in a certain style"""
238 def __init__(self
, style
, text
):
243 return "StyledText(%s, %s)" % (`self
.style`
, `self
.text`
)
248 def __aepack__(self
):
249 return pack({'ksty': self
.style
, 'ktxt': self
.text
}, 'STXT')
252 return IsInstance(x
, StyledText
)
255 """An AE text object with style, script and language specified"""
257 def __init__(self
, script
, style
, text
):
263 return "AEText(%s, %s, %s)" % (`self
.script`
, `self
.style`
, `self
.text`
)
268 def __aepack__(self
):
269 return pack({keyAEScriptTag
: self
.script
, keyAEStyles
: self
.style
,
270 keyAEText
: self
.text
}, typeAEText
)
273 return IsInstance(x
, AEText
)
276 """A text object with script and language specified"""
278 def __init__(self
, script
, language
, text
):
280 self
.language
= language
284 return "IntlText(%s, %s, %s)" % (`self
.script`
, `self
.language`
, `self
.text`
)
289 def __aepack__(self
):
290 return pack(struct
.pack('hh', self
.script
, self
.language
)+self
.text
,
294 return IsInstance(x
, IntlText
)
296 class IntlWritingCode
:
297 """An object representing script and language"""
299 def __init__(self
, script
, language
):
301 self
.language
= language
304 return "IntlWritingCode(%s, %s)" % (`self
.script`
, `self
.language`
)
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
),
313 def IsIntlWritingCode(x
):
314 return IsInstance(x
, IntlWritingCode
)
319 def __init__(self
, v
, h
):
324 return "QDPoint(%s, %s)" % (`self
.v`
, `self
.h`
)
327 return "(%d, %d)"%(self
.v
, self
.h
)
329 def __aepack__(self
):
330 return pack(struct
.pack('hh', self
.v
, self
.h
),
334 return IsInstance(x
, QDPoint
)
339 def __init__(self
, v0
, h0
, v1
, h1
):
346 return "QDRectangle(%s, %s, %s, %s)" % (`self
.v0`
, `self
.h0`
,
347 `self
.v1`
, `self
.h1`
)
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
),
356 def IsQDRectangle(x
):
357 return IsInstance(x
, QDRectangle
)
362 def __init__(self
, r
, g
, b
):
368 return "RGBColor(%s, %s, %s)" % (`self
.r`
, `self
.g`
, `self
.b`
)
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
),
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:
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):
412 s
= "ObjectSpecifier(%s, %s, %s" % (`self
.want`
, `self
.form`
, `self
.seld`
)
414 s
= s
+ ", %s)" % `self
.fr`
419 def __aepack__(self
):
420 return pack({'want': mktype(self
.want
),
421 'form': mkenum(self
.form
),
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
)
438 return "Property(%s, %s)" % (`self
.seld
.type`
, `self
.fr`
)
440 return "Property(%s)" % `self
.seld
.type`
444 return "Property %s of %s" % (str(self
.seld
), str(self
.fr
))
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):
460 ObjectSpecifier
.__init
__(self
, self
.want
, 'prop',
461 mktype(self
.which
), fr
)
464 rv
= "Property(%s"%`self
.seld
.type`
466 rv
= rv
+ ", fr=%s" % `self
.fr`
467 if self
.want
!= 'prop':
468 rv
= rv
+ ", want=%s" % `self
.want`
473 return "Property %s of %s" % (str(self
.seld
), str(self
.fr
))
475 return "Property %s" % str(self
.seld
)
478 class SelectableItem(ObjectSpecifier
):
480 def __init__(self
, want
, seld
, fr
= None):
486 elif IsComparison(seld
) or IsLogical(seld
):
489 # Breakout: specify both form and seld in a tuple
490 # (if you want ID or rele or somesuch)
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
)
507 return "%s(%s)" % (self
.__class
__.__name
__, `self
.seld`
)
508 return "%s(%s, %s)" % (self
.__class
__.__name
__, `self
.seld`
, `self
.fr`
)
512 if type(seld
) == StringType
:
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
)
523 s
= "%s %s" % (self
.__class
__.__name
__, ss
)
524 if self
.fr
: s
= s
+ " of %s" % str(self
.fr
)
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
]
534 raise AttributeError, name
537 class DelayedComponentItem
:
538 def __init__(self
, compclass
, fr
):
539 self
.compclass
= compclass
542 def __call__(self
, which
):
543 return self
.compclass(which
, self
.fr
)
546 return "%s(???, %s)" % (self
.__class
__.__name
__, `self
.fr`
)
549 return "selector for element %s of %s"%(self
.__class
__.__name
__, str(self
.fr
))
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')