PageRenderTime 346ms CodeModel.GetById 130ms app.highlight 18ms RepoModel.GetById 194ms app.codeStats 0ms

/Lib/plat-mac/MiniAEFrame.py

http://unladen-swallow.googlecode.com/
Python | 200 lines | 157 code | 28 blank | 15 comment | 21 complexity | a98f2365edc02443cb85659fc75dae03 MD5 | raw file
  1"""MiniAEFrame - A minimal AppleEvent Application framework.
  2
  3There are two classes:
  4    AEServer -- a mixin class offering nice AE handling.
  5    MiniApplication -- a very minimal alternative to FrameWork.py,
  6        only suitable for the simplest of AppleEvent servers.
  7"""
  8
  9from warnings import warnpy3k
 10warnpy3k("In 3.x, the MiniAEFrame module is removed.", stacklevel=2)
 11
 12import traceback
 13import MacOS
 14from Carbon import AE
 15from Carbon.AppleEvents import *
 16from Carbon import Evt
 17from Carbon.Events import *
 18from Carbon import Menu
 19from Carbon import Win
 20from Carbon.Windows import *
 21from Carbon import Qd
 22
 23import aetools
 24import EasyDialogs
 25
 26kHighLevelEvent = 23                # Not defined anywhere for Python yet?
 27
 28
 29class MiniApplication:
 30
 31    """A minimal FrameWork.Application-like class"""
 32
 33    def __init__(self):
 34        self.quitting = 0
 35        # Initialize menu
 36        self.appleid = 1
 37        self.quitid = 2
 38        Menu.ClearMenuBar()
 39        self.applemenu = applemenu = Menu.NewMenu(self.appleid, "\024")
 40        applemenu.AppendMenu("%s;(-" % self.getaboutmenutext())
 41        if MacOS.runtimemodel == 'ppc':
 42            applemenu.AppendResMenu('DRVR')
 43        applemenu.InsertMenu(0)
 44        self.quitmenu = Menu.NewMenu(self.quitid, "File")
 45        self.quitmenu.AppendMenu("Quit")
 46        self.quitmenu.SetItemCmd(1, ord("Q"))
 47        self.quitmenu.InsertMenu(0)
 48        Menu.DrawMenuBar()
 49
 50    def __del__(self):
 51        self.close()
 52
 53    def close(self):
 54        pass
 55
 56    def mainloop(self, mask = everyEvent, timeout = 60*60):
 57        while not self.quitting:
 58            self.dooneevent(mask, timeout)
 59
 60    def _quit(self):
 61        self.quitting = 1
 62
 63    def dooneevent(self, mask = everyEvent, timeout = 60*60):
 64        got, event = Evt.WaitNextEvent(mask, timeout)
 65        if got:
 66            self.lowlevelhandler(event)
 67
 68    def lowlevelhandler(self, event):
 69        what, message, when, where, modifiers = event
 70        h, v = where
 71        if what == kHighLevelEvent:
 72            msg = "High Level Event: %r %r" % (code(message), code(h | (v<<16)))
 73            try:
 74                AE.AEProcessAppleEvent(event)
 75            except AE.Error, err:
 76                print 'AE error: ', err
 77                print 'in', msg
 78                traceback.print_exc()
 79            return
 80        elif what == keyDown:
 81            c = chr(message & charCodeMask)
 82            if modifiers & cmdKey:
 83                if c == '.':
 84                    raise KeyboardInterrupt, "Command-period"
 85                if c == 'q':
 86                    if hasattr(MacOS, 'OutputSeen'):
 87                        MacOS.OutputSeen()
 88                    self.quitting = 1
 89                    return
 90        elif what == mouseDown:
 91            partcode, window = Win.FindWindow(where)
 92            if partcode == inMenuBar:
 93                result = Menu.MenuSelect(where)
 94                id = (result>>16) & 0xffff      # Hi word
 95                item = result & 0xffff      # Lo word
 96                if id == self.appleid:
 97                    if item == 1:
 98                        EasyDialogs.Message(self.getabouttext())
 99                    elif item > 1 and hasattr(Menu, 'OpenDeskAcc'):
100                        name = self.applemenu.GetMenuItemText(item)
101                        Menu.OpenDeskAcc(name)
102                elif id == self.quitid and item == 1:
103                    if hasattr(MacOS, 'OutputSeen'):
104                        MacOS.OutputSeen()
105                    self.quitting = 1
106                Menu.HiliteMenu(0)
107                return
108        # Anything not handled is passed to Python/SIOUX
109        if hasattr(MacOS, 'HandleEvent'):
110            MacOS.HandleEvent(event)
111        else:
112            print "Unhandled event:", event
113
114    def getabouttext(self):
115        return self.__class__.__name__
116
117    def getaboutmenutext(self):
118        return "About %s\311" % self.__class__.__name__
119
120
121class AEServer:
122
123    def __init__(self):
124        self.ae_handlers = {}
125
126    def installaehandler(self, classe, type, callback):
127        AE.AEInstallEventHandler(classe, type, self.callback_wrapper)
128        self.ae_handlers[(classe, type)] = callback
129
130    def close(self):
131        for classe, type in self.ae_handlers.keys():
132            AE.AERemoveEventHandler(classe, type)
133
134    def callback_wrapper(self, _request, _reply):
135        _parameters, _attributes = aetools.unpackevent(_request)
136        _class = _attributes['evcl'].type
137        _type = _attributes['evid'].type
138
139        if self.ae_handlers.has_key((_class, _type)):
140            _function = self.ae_handlers[(_class, _type)]
141        elif self.ae_handlers.has_key((_class, '****')):
142            _function = self.ae_handlers[(_class, '****')]
143        elif self.ae_handlers.has_key(('****', '****')):
144            _function = self.ae_handlers[('****', '****')]
145        else:
146            raise 'Cannot happen: AE callback without handler', (_class, _type)
147
148        # XXXX Do key-to-name mapping here
149
150        _parameters['_attributes'] = _attributes
151        _parameters['_class'] = _class
152        _parameters['_type'] = _type
153        if _parameters.has_key('----'):
154            _object = _parameters['----']
155            del _parameters['----']
156            # The try/except that used to be here can mask programmer errors.
157            # Let the program crash, the programmer can always add a **args
158            # to the formal parameter list.
159            rv = _function(_object, **_parameters)
160        else:
161            #Same try/except comment as above
162            rv = _function(**_parameters)
163
164        if rv is None:
165            aetools.packevent(_reply, {})
166        else:
167            aetools.packevent(_reply, {'----':rv})
168
169
170def code(x):
171    "Convert a long int to the 4-character code it really is"
172    s = ''
173    for i in range(4):
174        x, c = divmod(x, 256)
175        s = chr(c) + s
176    return s
177
178class _Test(AEServer, MiniApplication):
179    """Mini test application, handles required events"""
180
181    def __init__(self):
182        MiniApplication.__init__(self)
183        AEServer.__init__(self)
184        self.installaehandler('aevt', 'oapp', self.open_app)
185        self.installaehandler('aevt', 'quit', self.quit)
186        self.installaehandler('****', '****', self.other)
187        self.mainloop()
188
189    def quit(self, **args):
190        self._quit()
191
192    def open_app(self, **args):
193        pass
194
195    def other(self, _object=None, _class=None, _type=None, **args):
196        print 'AppleEvent', (_class, _type), 'for', _object, 'Other args:', args
197
198
199if __name__ == '__main__':
200    _Test()