1"""aetypes - Python objects representing various AE types."""
2
3from warnings import warnpy3k
4warnpy3k("In 3.x, the aetypes module is removed.", stacklevel=2)
5
6from Carbon.AppleEvents import *
7import struct
8from types import *
9import string
10
11#
12# convoluted, since there are cyclic dependencies between this file and
13# aetools_convert.
14#
15def pack(*args, **kwargs):
16    from aepack import pack
17    return pack( *args, **kwargs)
18
19def nice(s):
20    """'nice' representation of an object"""
21    if type(s) is StringType: return repr(s)
22    else: return str(s)
23
24class Unknown:
25    """An uninterpreted AE object"""
26
27    def __init__(self, type, data):
28        self.type = type
29        self.data = data
30
31    def __repr__(self):
32        return "Unknown(%r, %r)" % (self.type, self.data)
33
34    def __aepack__(self):
35        return pack(self.data, self.type)
36
37class Enum:
38    """An AE enumeration value"""
39
40    def __init__(self, enum):
41        self.enum = "%-4.4s" % str(enum)
42
43    def __repr__(self):
44        return "Enum(%r)" % (self.enum,)
45
46    def __str__(self):
47        return string.strip(self.enum)
48
49    def __aepack__(self):
50        return pack(self.enum, typeEnumeration)
51
52def IsEnum(x):
53    return isinstance(x, Enum)
54
55def mkenum(enum):
56    if IsEnum(enum): return enum
57    return Enum(enum)
58
59# Jack changed the way this is done
60class InsertionLoc:
61    def __init__(self, of, pos):
62        self.of = of
63        self.pos = pos
64
65    def __repr__(self):
66        return "InsertionLoc(%r, %r)" % (self.of, self.pos)
67
68    def __aepack__(self):
69        rec = {'kobj': self.of, 'kpos': self.pos}
70        return pack(rec, forcetype='insl')
71
72# Convenience functions for dsp:
73def beginning(of):
74    return InsertionLoc(of, Enum('bgng'))
75
76def end(of):
77    return InsertionLoc(of, Enum('end '))
78
79class Boolean:
80    """An AE boolean value"""
81
82    def __init__(self, bool):
83        self.bool = (not not bool)
84
85    def __repr__(self):
86        return "Boolean(%r)" % (self.bool,)
87
88    def __str__(self):
89        if self.bool:
90            return "True"
91        else:
92            return "False"
93
94    def __aepack__(self):
95        return pack(struct.pack('b', self.bool), 'bool')
96
97def IsBoolean(x):
98    return isinstance(x, Boolean)
99
100def mkboolean(bool):
101    if IsBoolean(bool): return bool
102    return Boolean(bool)
103
104class Type:
105    """An AE 4-char typename object"""
106
107    def __init__(self, type):
108        self.type = "%-4.4s" % str(type)
109
110    def __repr__(self):
111        return "Type(%r)" % (self.type,)
112
113    def __str__(self):
114        return string.strip(self.type)
115
116    def __aepack__(self):
117        return pack(self.type, typeType)
118
119def IsType(x):
120    return isinstance(x, Type)
121
122def mktype(type):
123    if IsType(type): return type
124    return Type(type)
125
126
127class Keyword:
128    """An AE 4-char keyword object"""
129
130    def __init__(self, keyword):
131        self.keyword = "%-4.4s" % str(keyword)
132
133    def __repr__(self):
134        return "Keyword(%r)" % repr(self.keyword)
135
136    def __str__(self):
137        return string.strip(self.keyword)
138
139    def __aepack__(self):
140        return pack(self.keyword, typeKeyword)
141
142def IsKeyword(x):
143    return isinstance(x, Keyword)
144
145class Range:
146    """An AE range object"""
147
148    def __init__(self, start, stop):
149        self.start = start
150        self.stop = stop
151
152    def __repr__(self):
153        return "Range(%r, %r)" % (self.start, self.stop)
154
155    def __str__(self):
156        return "%s thru %s" % (nice(self.start), nice(self.stop))
157
158    def __aepack__(self):
159        return pack({'star': self.start, 'stop': self.stop}, 'rang')
160
161def IsRange(x):
162    return isinstance(x, Range)
163
164class Comparison:
165    """An AE Comparison"""
166
167    def __init__(self, obj1, relo, obj2):
168        self.obj1 = obj1
169        self.relo = "%-4.4s" % str(relo)
170        self.obj2 = obj2
171
172    def __repr__(self):
173        return "Comparison(%r, %r, %r)" % (self.obj1, self.relo, self.obj2)
174
175    def __str__(self):
176        return "%s %s %s" % (nice(self.obj1), string.strip(self.relo), nice(self.obj2))
177
178    def __aepack__(self):
179        return pack({'obj1': self.obj1,
180                 'relo': mkenum(self.relo),
181                 'obj2': self.obj2},
182                'cmpd')
183
184def IsComparison(x):
185    return isinstance(x, Comparison)
186
187class NComparison(Comparison):
188    # The class attribute 'relo' must be set in a subclass
189
190    def __init__(self, obj1, obj2):
191        Comparison.__init__(obj1, self.relo, obj2)
192
193class Ordinal:
194    """An AE Ordinal"""
195
196    def __init__(self, abso):
197#       self.obj1 = obj1
198        self.abso = "%-4.4s" % str(abso)
199
200    def __repr__(self):
201        return "Ordinal(%r)" % (self.abso,)
202
203    def __str__(self):
204        return "%s" % (string.strip(self.abso))
205
206    def __aepack__(self):
207        return pack(self.abso, 'abso')
208
209def IsOrdinal(x):
210    return isinstance(x, Ordinal)
211
212class NOrdinal(Ordinal):
213    # The class attribute 'abso' must be set in a subclass
214
215    def __init__(self):
216        Ordinal.__init__(self, self.abso)
217
218class Logical:
219    """An AE logical expression object"""
220
221    def __init__(self, logc, term):
222        self.logc = "%-4.4s" % str(logc)
223        self.term = term
224
225    def __repr__(self):
226        return "Logical(%r, %r)" % (self.logc, self.term)
227
228    def __str__(self):
229        if type(self.term) == ListType and len(self.term) == 2:
230            return "%s %s %s" % (nice(self.term[0]),
231                                 string.strip(self.logc),
232                                 nice(self.term[1]))
233        else:
234            return "%s(%s)" % (string.strip(self.logc), nice(self.term))
235
236    def __aepack__(self):
237        return pack({'logc': mkenum(self.logc), 'term': self.term}, 'logi')
238
239def IsLogical(x):
240    return isinstance(x, Logical)
241
242class StyledText:
243    """An AE object respresenting text in a certain style"""
244
245    def __init__(self, style, text):
246        self.style = style
247        self.text = text
248
249    def __repr__(self):
250        return "StyledText(%r, %r)" % (self.style, self.text)
251
252    def __str__(self):
253        return self.text
254
255    def __aepack__(self):
256        return pack({'ksty': self.style, 'ktxt': self.text}, 'STXT')
257
258def IsStyledText(x):
259    return isinstance(x, StyledText)
260
261class AEText:
262    """An AE text object with style, script and language specified"""
263
264    def __init__(self, script, style, text):
265        self.script = script
266        self.style = style
267        self.text = text
268
269    def __repr__(self):
270        return "AEText(%r, %r, %r)" % (self.script, self.style, self.text)
271
272    def __str__(self):
273        return self.text
274
275    def __aepack__(self):
276        return pack({keyAEScriptTag: self.script, keyAEStyles: self.style,
277                 keyAEText: self.text}, typeAEText)
278
279def IsAEText(x):
280    return isinstance(x, AEText)
281
282class IntlText:
283    """A text object with script and language specified"""
284
285    def __init__(self, script, language, text):
286        self.script = script
287        self.language = language
288        self.text = text
289
290    def __repr__(self):
291        return "IntlText(%r, %r, %r)" % (self.script, self.language, self.text)
292
293    def __str__(self):
294        return self.text
295
296    def __aepack__(self):
297        return pack(struct.pack('hh', self.script, self.language)+self.text,
298            typeIntlText)
299
300def IsIntlText(x):
301    return isinstance(x, IntlText)
302
303class IntlWritingCode:
304    """An object representing script and language"""
305
306    def __init__(self, script, language):
307        self.script = script
308        self.language = language
309
310    def __repr__(self):
311        return "IntlWritingCode(%r, %r)" % (self.script, self.language)
312
313    def __str__(self):
314        return "script system %d, language %d"%(self.script, self.language)
315
316    def __aepack__(self):
317        return pack(struct.pack('hh', self.script, self.language),
318            typeIntlWritingCode)
319
320def IsIntlWritingCode(x):
321    return isinstance(x, IntlWritingCode)
322
323class QDPoint:
324    """A point"""
325
326    def __init__(self, v, h):
327        self.v = v
328        self.h = h
329
330    def __repr__(self):
331        return "QDPoint(%r, %r)" % (self.v, self.h)
332
333    def __str__(self):
334        return "(%d, %d)"%(self.v, self.h)
335
336    def __aepack__(self):
337        return pack(struct.pack('hh', self.v, self.h),
338            typeQDPoint)
339
340def IsQDPoint(x):
341    return isinstance(x, QDPoint)
342
343class QDRectangle:
344    """A rectangle"""
345
346    def __init__(self, v0, h0, v1, h1):
347        self.v0 = v0
348        self.h0 = h0
349        self.v1 = v1
350        self.h1 = h1
351
352    def __repr__(self):
353        return "QDRectangle(%r, %r, %r, %r)" % (self.v0, self.h0, self.v1, self.h1)
354
355    def __str__(self):
356        return "(%d, %d)-(%d, %d)"%(self.v0, self.h0, self.v1, self.h1)
357
358    def __aepack__(self):
359        return pack(struct.pack('hhhh', self.v0, self.h0, self.v1, self.h1),
360            typeQDRectangle)
361
362def IsQDRectangle(x):
363    return isinstance(x, QDRectangle)
364
365class RGBColor:
366    """An RGB color"""
367
368    def __init__(self, r, g, b):
369        self.r = r
370        self.g = g
371        self.b = b
372
373    def __repr__(self):
374        return "RGBColor(%r, %r, %r)" % (self.r, self.g, self.b)
375
376    def __str__(self):
377        return "0x%x red, 0x%x green, 0x%x blue"% (self.r, self.g, self.b)
378
379    def __aepack__(self):
380        return pack(struct.pack('hhh', self.r, self.g, self.b),
381            typeRGBColor)
382
383def IsRGBColor(x):
384    return isinstance(x, RGBColor)
385
386class ObjectSpecifier:
387
388    """A class for constructing and manipulation AE object specifiers in python.
389
390    An object specifier is actually a record with four fields:
391
392    key type    description
393    --- ----    -----------
394
395    'want'  type    4-char class code of thing we want,
396            e.g. word, paragraph or property
397
398    'form'  enum    how we specify which 'want' thing(s) we want,
399            e.g. by index, by range, by name, or by property specifier
400
401    'seld'  any which thing(s) we want,
402            e.g. its index, its name, or its property specifier
403
404    'from'  object  the object in which it is contained,
405            or null, meaning look for it in the application
406
407    Note that we don't call this class plain "Object", since that name
408    is likely to be used by the application.
409    """
410
411    def __init__(self, want, form, seld, fr = None):
412        self.want = want
413        self.form = form
414        self.seld = seld
415        self.fr = fr
416
417    def __repr__(self):
418        s = "ObjectSpecifier(%r, %r, %r" % (self.want, self.form, self.seld)
419        if self.fr:
420            s = s + ", %r)" % (self.fr,)
421        else:
422            s = s + ")"
423        return s
424
425    def __aepack__(self):
426        return pack({'want': mktype(self.want),
427                 'form': mkenum(self.form),
428                 'seld': self.seld,
429                 'from': self.fr},
430                'obj ')
431
432def IsObjectSpecifier(x):
433    return isinstance(x, ObjectSpecifier)
434
435
436# Backwards compatibility, sigh...
437class Property(ObjectSpecifier):
438
439    def __init__(self, which, fr = None, want='prop'):
440        ObjectSpecifier.__init__(self, want, 'prop', mktype(which), fr)
441
442    def __repr__(self):
443        if self.fr:
444            return "Property(%r, %r)" % (self.seld.type, self.fr)
445        else:
446            return "Property(%r)" % (self.seld.type,)
447
448    def __str__(self):
449        if self.fr:
450            return "Property %s of %s" % (str(self.seld), str(self.fr))
451        else:
452            return "Property %s" % str(self.seld)
453
454
455class NProperty(ObjectSpecifier):
456    # Subclasses *must* self baseclass attributes:
457    # want is the type of this property
458    # which is the property name of this property
459
460    def __init__(self, fr = None):
461        #try:
462        #   dummy = self.want
463        #except:
464        #   self.want = 'prop'
465        self.want = 'prop'
466        ObjectSpecifier.__init__(self, self.want, 'prop',
467                    mktype(self.which), fr)
468
469    def __repr__(self):
470        rv = "Property(%r" % (self.seld.type,)
471        if self.fr:
472            rv = rv + ", fr=%r" % (self.fr,)
473        if self.want != 'prop':
474            rv = rv + ", want=%r" % (self.want,)
475        return rv + ")"
476
477    def __str__(self):
478        if self.fr:
479            return "Property %s of %s" % (str(self.seld), str(self.fr))
480        else:
481            return "Property %s" % str(self.seld)
482
483
484class SelectableItem(ObjectSpecifier):
485
486    def __init__(self, want, seld, fr = None):
487        t = type(seld)
488        if t == StringType:
489            form = 'name'
490        elif IsRange(seld):
491            form = 'rang'
492        elif IsComparison(seld) or IsLogical(seld):
493            form = 'test'
494        elif t == TupleType:
495            # Breakout: specify both form and seld in a tuple
496            # (if you want ID or rele or somesuch)
497            form, seld = seld
498        else:
499            form = 'indx'
500        ObjectSpecifier.__init__(self, want, form, seld, fr)
501
502
503class ComponentItem(SelectableItem):
504    # Derived classes *must* set the *class attribute* 'want' to some constant
505    # Also, dictionaries _propdict and _elemdict must be set to map property
506    # and element names to the correct classes
507
508    _propdict = {}
509    _elemdict = {}
510    def __init__(self, which, fr = None):
511        SelectableItem.__init__(self, self.want, which, fr)
512
513    def __repr__(self):
514        if not self.fr:
515            return "%s(%r)" % (self.__class__.__name__, self.seld)
516        return "%s(%r, %r)" % (self.__class__.__name__, self.seld, self.fr)
517
518    def __str__(self):
519        seld = self.seld
520        if type(seld) == StringType:
521            ss = repr(seld)
522        elif IsRange(seld):
523            start, stop = seld.start, seld.stop
524            if type(start) == InstanceType == type(stop) and \
525               start.__class__ == self.__class__ == stop.__class__:
526                ss = str(start.seld) + " thru " + str(stop.seld)
527            else:
528                ss = str(seld)
529        else:
530            ss = str(seld)
531        s = "%s %s" % (self.__class__.__name__, ss)
532        if self.fr: s = s + " of %s" % str(self.fr)
533        return s
534
535    def __getattr__(self, name):
536        if name in self._elemdict:
537            cls = self._elemdict[name]
538            return DelayedComponentItem(cls, self)
539        if name in self._propdict:
540            cls = self._propdict[name]
541            return cls(self)
542        raise AttributeError, name
543
544
545class DelayedComponentItem:
546    def __init__(self, compclass, fr):
547        self.compclass = compclass
548        self.fr = fr
549
550    def __call__(self, which):
551        return self.compclass(which, self.fr)
552
553    def __repr__(self):
554        return "%s(???, %r)" % (self.__class__.__name__, self.fr)
555
556    def __str__(self):
557        return "selector for element %s of %s"%(self.__class__.__name__, str(self.fr))
558
559template = """
560class %s(ComponentItem): want = '%s'
561"""
562
563exec template % ("Text", 'text')
564exec template % ("Character", 'cha ')
565exec template % ("Word", 'cwor')
566exec template % ("Line", 'clin')
567exec template % ("paragraph", 'cpar')
568exec template % ("Window", 'cwin')
569exec template % ("Document", 'docu')
570exec template % ("File", 'file')
571exec template % ("InsertionPoint", 'cins')
572