/Lib/plat-mac/MiniAEFrame.py

http://unladen-swallow.googlecode.com/ · Python · 200 lines · 149 code · 35 blank · 16 comment · 33 complexity · a98f2365edc02443cb85659fc75dae03 MD5 · raw file

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