home *** CD-ROM | disk | FTP | other *** search
/ AppleScript - The Beta Release / AppleScript - The Beta Release.iso / Documentation / develop / Better Apple Event Coding / Code Samples / UAppleObject.h < prev    next >
Encoding:
Text File  |  1992-10-16  |  11.2 KB  |  281 lines  |  [TEXT/MPS ]

  1. // UAppleObject.h
  2. // by Eric Berdahl
  3. // AppleLink: BERDAHL
  4. // Interget: eric_berdahl@taligent.com
  5. // May XX, 1992
  6. //
  7. // Copyright © 1992 Eric M. Berdahl
  8. // All rights reserved.
  9. //
  10. // LICENSE
  11. //
  12. // UAppleObject is provided under the ego-ware™ system.  If you send me a note
  13. // telling me how cool you think it UAppleObject is, you may incorporate it into
  14. // any product you like (six-packs of good beer are also acceptable, no C.O.D.
  15. // shipments, please).  Also, you must keep all copyright and other notices in
  16. // the source code, especially MY NAME (The system is called ego-ware™.  Get it?).
  17. //
  18. // THEORY OF OPERATION
  19. //
  20. // This unit includes and uses two classes for the processing of AppleEvents,
  21. // especially AppleEvents whose targets are objects in the application domain
  22. // (ie: object specifiers).  By properly utilizing TAppleObjectDispatcher and
  23. // MAppleObject, you should be able to, very easily, add full AppleEvent support
  24. // to any well designed object-oriented application.
  25. //
  26. // MAppleObject represents an encapsulation of the standard AppleEvent object
  27. // model.  The various pure virtual methods are the hooks for the AppleEvent
  28. // world to be translated into application domain instances.  Thus, the functionality
  29. // of MAppleObject is based on managing the translation between Object Model
  30. // categories and application domain instances.
  31. //
  32. // TAppleObjectDispatcher has a very different, yet equally important, function.
  33. // Whereas, MAppleObject defines the protocol for inter-object communication at a
  34. // very high level, TAppleObjectDispatcher encapsulates the mechanics of translating
  35. // the AppleEvent protocol into C++ objects and methods.  It provides a generic
  36. // interface for handling AppleEvents and translating AppleEvent object specifiers
  37. // into application domain object instances.  TAppleObjectDispatcher is implemented
  38. // by wrapping the Object Support Library for the object model-instance translation.
  39. //
  40. // Subclasses of TAppleObjectDispatcher may be created to add advanced OSL topics
  41. // to the melange of object distribution.  Things I’d like to include in future
  42. // versions of this product, if any, include support for marking and lists.
  43. // Admitedly, what appears here is not the be all end all of object processing;
  44. // it’s simply a second approximation proof of concept that this is possible,
  45. // with the potential of being exceptionally easy to use and program.
  46.  
  47. #ifndef _UAPPLEOBJECT_
  48. #define _UAPPLEOBJECT_
  49.  
  50. #ifndef __APPLEEVENTS__
  51. #include <AppleEvents.h>
  52. #endif
  53.  
  54. enum
  55. {
  56.     errAppleObjectDispatcherAlreadyInstalled = 1000,
  57.     errAlreadyHaveAnApplication = 1001,
  58.     errCantCopyTheApplication = 1002
  59. };
  60.  
  61.  
  62. class TAppleObjectDispatcher;
  63. class MAppleObject;
  64.  
  65. class TAppleObjectDispatcher
  66. {
  67. public:
  68.     TAppleObjectDispatcher();
  69.     virtual ~TAppleObjectDispatcher();
  70.  
  71.     virtual void Install();
  72.  
  73.     virtual MAppleObject* ExtractObject(const AEDesc& descriptor);
  74.     virtual void StuffDescriptor(AEDesc& descriptor, MAppleObject* object);
  75.  
  76.     virtual void HandleAppleEvent(const AppleEvent& message,
  77.                                   AppleEvent& reply,
  78.                                   long refCon);
  79.  
  80.     virtual void AccessContainedObjects(DescType desiredClass,
  81.                                         const AEDesc& container,
  82.                                         DescType containerClass,
  83.                                         DescType form,
  84.                                         const AEDesc& selectionData,
  85.                                         AEDesc& value,
  86.                                         long refCon);
  87.  
  88.     virtual long CountObjects(const AEDesc& containerToken,
  89.                               DescType countObjectsOfType);
  90.  
  91.     virtual Boolean CompareObjects(DescType operation,
  92.                                    const AEDesc& obj1,
  93.                                    const AEDesc& obj2);
  94.  
  95.     virtual void DisposeToken(AEDesc& unneededToken);
  96.  
  97.     virtual MAppleObject* GetTarget(const AppleEvent& message);
  98.  
  99.     virtual void SetTokenObjectDisposal(MAppleObject* tokenObject,
  100.                                        Boolean needsDisposal);
  101.         // In addition to the needsDisposal argument returned from
  102.         // GetContainedObject, an application may control the management of an
  103.         // object by calling the SetTokenObjectDisposal routine.  If true is
  104.         // passed for needsDisposal, the tokenObject will be marked as needing
  105.         // disposal if it is not previously marked as such.  If false is passed
  106.         // for needsDisposal, the tokenObject will be marked as not needing
  107.         // disposal if it has previously been marked as such.
  108.  
  109.     virtual Boolean GetTokenObjectDisposal(const MAppleObject* tokenObject);
  110.         // If you wish to inquire about the disposal status of any particular
  111.         // object, this routine will return true if it is set to be deleted
  112.         // when its token is disposed.
  113.  
  114.     virtual MAppleObject* ResolveSpecifier(AEDesc& objectSpecifier);
  115.         // In the course of processing an AppleEvent, you may run across an object
  116.         // of typeObjectSpecifier.  If so, you may resolve that into a specific
  117.         // object by calling ResolveSpecifier.  This routine will never return
  118.         // nil.  If no such object exists or some other exception occurs, a
  119.         // failure will be thrown.  In the time of targeting AppleEvents, if
  120.         // the direct parameter is an object specifier, this function will
  121.         // be called by the framework.
  122.  
  123.     virtual void InstallAppleEventHandler(AEEventClass theClass, AEEventID theID,
  124.                                           long refCon);
  125.  
  126.     static TAppleObjectDispatcher* GetDispatcher();
  127.  
  128. private:
  129.     static pascal OSErr AppleEventHandler(const AppleEvent* message,
  130.                                           AppleEvent* reply,
  131.                                           long refCon);
  132.  
  133.     static pascal OSErr OSLObjectAccessorHandler(DescType desiredClass,
  134.                                                  const AEDesc* container,
  135.                                                  DescType containerClass,
  136.                                                  DescType form,
  137.                                                  const AEDesc* selectionData,
  138.                                                  AEDesc* value,
  139.                                                  long refCon);
  140.  
  141.     static pascal OSErr OSLCountObjectsHandler(DescType countObjectsOfType,
  142.                                                DescType containerClass,
  143.                                                const AEDesc* containerToken,
  144.                                                long* result);
  145.  
  146.     static pascal OSErr OSLCompareObjectsHandler(DescType operation,
  147.                                                  const AEDesc *obj1,
  148.                                                  const AEDesc *obj2,
  149.                                                  Boolean *result);
  150.  
  151.     static pascal OSErr OSLDisposeTokenHandler(AEDesc* unneededToken);
  152.  
  153.     static TAppleObjectDispatcher* fgDispatcher;
  154.     static Boolean    fgInited;
  155.  
  156.     MAppleObject*** fDisposalList;
  157.     long fDisposalListSize;
  158.         // List of objects to be disposed when we are finished with them.
  159.  
  160.     MAppleObject*    fApplication;
  161. };
  162.  
  163.  
  164. class MAppleObject
  165. {
  166. public:
  167.     MAppleObject();
  168.         // default constructor
  169.  
  170.     MAppleObject(const MAppleObject& copy);
  171.         // copy constructor
  172.  
  173.     virtual ~MAppleObject();
  174.         // destructor, duh
  175.  
  176.     MAppleObject& operator=(const MAppleObject& assignTo);
  177.         // Assignment operator
  178.  
  179.     virtual void DoAppleEvent(const AppleEvent& message,
  180.                               AppleEvent& reply,
  181.                               long refCon);
  182.         // Once an AppleEvent has been resolved to the point of finding a
  183.         // specific object which is its target, it will be sent the
  184.         // DoAppleEvent message.  The AppleEvent message and reply are in
  185.         // their respective arguments, as is the refCon.  Upon return from
  186.         // this method, the AppleEvent handler will exit (this method is
  187.         // called from within the handler itself) normally.  If an error
  188.         // occurs, throw a failure.  The failure error will be caught and
  189.         // returned as appropriate.
  190.  
  191.     virtual DescType GetAppleClass() const = 0;
  192.         // Each instance must be able to inform the framework what type of
  193.         // AppleEvent object it is.  GetAppleClass must return the appropriate
  194.         // DescType for the object.
  195.  
  196.     virtual long CountContainedObjects(DescType ofType);
  197.         // Each AppleObject must be able to return a count of the number of
  198.         // AppleEvent objects contained within it.  The desiredType parameter
  199.         // informs the object what types of objects it should count.  All values
  200.         // returned from this method will be considered valid from the framework.
  201.         // Throw a failure if an exception occurs.
  202.  
  203.     virtual Boolean CompareAppleObjects(DescType operation,
  204.                                         const MAppleObject& toWhat);
  205.         // Given an object and a comparison operation to perform, this
  206.         // method must be overridden to return a Boolean value indicating
  207.         // whether the comparison is a true comparison or a false comparison
  208.         // (e.g. 1 > 2 is a false comparison).  The semantics for this
  209.         // comparison are <this> <operation> <toWhat>.  This ordering will
  210.         // be important for comparisons that are not commutative (e.g. less
  211.         // than, greater than, equal to.  To cut down on the amount of code you
  212.         // wish to write, you may wish to use a subclass of MAppleObject of your
  213.         // own, say MMyAppleObject, where you override CompareAppleObjects to
  214.         // catch the less than, greater than, equal to, before, after and other
  215.         // generic ordering operations.  MMyAppleObject would then define another
  216.         // pure virtual function that returned an enum indicated wheter the
  217.         // two objects ordering positions (ala the C library routine strcmp).
  218.         // Such a function is left as an exercise for the reader.
  219.  
  220.     virtual MAppleObject* GetContainedObject(DescType desiredType,
  221.                                              DescType keyForm,
  222.                                              const AEDesc& keyData,
  223.                                              Boolean& needDisposal);
  224.         // An AppleObject must be able to return objects contained within it.
  225.         // The desiredType, keyForm, and keyData arguments indicate to the
  226.         // method which kind of object is desired.  The requested object is
  227.         // returned as the function result.
  228.         //
  229.         // If the resulting object was created by the method (ie: it was
  230.         // “lazy evaluated” into existance),  return true for needDisposal.
  231.         // The assumption here is that the object should be deleted when it
  232.         // is no longer needed for resolution of an object specifier.  If the
  233.         // resulting object was previously in existance (e.g. it is an object of
  234.         // your application engine, or is one of your base abstractions), return
  235.         // false for needDisposal.  In that case, the object will not be deleted
  236.         // by the UAppleObject framework and you will need to manage the storage
  237.         // yourself.
  238.         //
  239.         // Returning nil from this method will cause the framework to throw
  240.         // the errAENoSuchObject (???) error.  If another error is appropriate
  241.         // or more descriptive, throw the appropriate failure before returning.
  242.  
  243.     static void GotRequiredParameters(const AppleEvent& theAppleEvent);
  244.         // This routine is here for convenience.  To do AppleEvent processing
  245.         // “right”, you really want to check that you have everything the
  246.         // sender sent you.  Almost every good AppleEvent sample will have this
  247.         // routine and will call it from within the handlers.  Since all handling
  248.         // is done from within an MAppleObject (?), it makes sense for this to
  249.         // be a member function of MAppleObject.  However, the member function
  250.         // really doesn’t need access to the object itself, so it is static
  251.         // (ie: it can be called from anywhere).
  252.  
  253.     static void InitAppleObject(TAppleObjectDispatcher* dispatcher = nil);
  254.         // This function should be called exactly once.  It should be called
  255.         // after initializing the toolbox and before entering your application’s
  256.         // main event loop.  InitAppleObject initializes the toolbox AppleEvent
  257.         // manager to recognize the unit procedures.
  258.  
  259.     static void SetDefaultAppleObject(MAppleObject* defaultObject);
  260.     static MAppleObject* GetDefaultAppleObject();
  261. private:
  262.     static MAppleObject*    fgDefaultAppleObject;
  263.  
  264.     static Boolean fgInited;
  265.         // Used to ensure that the unit is only debugged once.
  266. };
  267.  
  268.  
  269. inline TAppleObjectDispatcher* TAppleObjectDispatcher::GetDispatcher()
  270. {
  271.     return fgDispatcher;
  272. }
  273.  
  274.  
  275. inline MAppleObject* MAppleObject::GetDefaultAppleObject()
  276. {
  277.     return fgDefaultAppleObject;
  278. }
  279.  
  280.  
  281. #endif