4 Replies Latest reply on Nov 17, 2008 3:23 PM by ssmiley483

    Defining and raising custom events

    ssmiley483
      I'm trying to design and build a re-usable Cast Library that can be included in a variety of other Director projects. This library is going to provide an interface to attached Bar Code Readers that show up as a keyboard on the computer and also provides interfaces for interacting with some external software.

      My problem is in figuring out how to define and raise custom events from this Cast Library. Currently I have it implemented in a Global Script within the library. However all it seems I can do from the script is call a pre-defined function that the containing movie has to implement. This doesn't really support having multiple listeners for events.

      There are two events I'm trying to define and raise:
      1. Notification when a barcode tag is scanned
      2. Notification when a data lookup from the server completes

      The typical application flow is that a parent director movie will sit in an idle mode waiting for a TagScan event to be raised. After the TagScan event, a request is sent to a central server to retrieve information associated with the barcode that was scanned. Since we don't want the UI hanging while waiting for the data to come back, we need another event notification when the data is available for use.

      So my question is really in two parts:
      1. Is my approach of using a global script in an External Cast Library the best way to implement a re-usable module?
      2. Is there a way to define and raise custom events from a global script?

      Thanks in advance,
      Shawn.
        • 1. Re: Defining and raising custom events
          Production Monkey Level 3
          1. The best way to create reusable code is to use Behaviors and Parent scripts. Some 98% of your code should be one of these two types - not movie scripts.

          2. By "global script" I take it that you mean a set of functions in a movie script. If so, then that is not a good approach.

          Here's the skeleton of how I would approach this. An event system at its basic level is nothing more than setting up callbacks with an object that polls the status of other objects. A callback is when an object passes a reference to itself and one of its handler names to another object. This enables the second object to make a call back to the first object. When it makes this call, is up to the second object.

          What you need is an object that monitors the asynchronous actions of the barcode reader and data retrieval from the server. Create a Parent script with the following code.

          -- Bar Code Monitor

          property pEvents -- list of events and objects registered to be called when an event happens.
          property pTimeOb -- timeout object used for periodic checking/polling of the status of various asynchronous actions.


          on new me
          pEvents = [#BarcodeScanned:[], #DataReady:[]]
          pTimeOb = timeout().new("BarcodeMonitor", 200, #CheckAsyncStatus, me) -- "200" means we check five times a second.
          return me
          end new



          on addEventListener me, CallbackObject, CallbackHandler, Event -- script instance, Symbol, Symbol
          -- may want to add argument validation here.

          CallBackInfo = [#CallbackObject:CallbackObject, #CallbackHandler:CallbackHandler]
          pEvents[Event].add(CallBackInfo)
          end addEventListener


          on removeEventListener me, CallbackObject, CallbackHandler, Event -- script instance, Symbol, Symbol
          -- code that traverses the list and removes any matching object and handler combinations for the specified Event.
          end removeEventListener


          on CheckAsyncStatus me, Timeob
          -- check the status of various asynchronous barcode stuff that is going on.

          -- Sample callback
          -- At this point some data is ready and has been retrieved
          Data = "whatever the data is"
          EventCallBacks = pEvents.DataReady
          repeat with CallBackInfo in EventCallBacks
          call(CallBackInfo.CallbackHandler, CallBackInfo.CallbackObject, Data)
          end repeat
          end CheckAsyncStatus
          ----------------------------------------------------------------------

          The above code sets up a mechanism for registering callbacks with the "bar code Monitor" object and uses a timeout object to periodically check the status of asynchronous actions.

          Now any object that wants to be notified of an event simply registers itself through the addEventListener method. I.E. lets say we want our global control object to listen for returned data. The following Parent script would set things up.

          -- control

          global gBarCodeMonitor

          on new me
          gBarCodeMonitor.addEventListener(me, #processData, #DataReady)
          return me
          end new


          on processData me, Data
          -- do something with the data
          end processData
          -------------------------------------------------------------------------


          You would then create your objects in preparemovie.

          global gBarCodeMonitor
          global gControl

          on prepareMovie
          -- setup Global Singletons

          if gBarCodeMonitor.voidP then
          gBarCodeMonitor = script("Bar Code Monitor").new()
          end if

          if gControl.voidP then
          gControl = script("Control").new()
          end if
          end prepareMovie
          ---------------------------------------------------------------------


          With this setup you can have multiple objects register for an event and a single object can register with multiple events.

          If you are unfamiliar with Parent scripts. Then take some time to learn. Your programming life will become much easier the day you go OOP.

          I did not test the code, so there may be a typo or something. But the basic idea is there.
          • 2. Re: Defining and raising custom events
            matthewmaday
            Answer to part A - I don't externalize my scripts. I would LOVE to like you can in Flash but it is always problematic in Director.

            Answer to part B - barcode readers emulate (or can be set to emulate) keyboard entries. I simply set the focus of an offscreen field and monitor it at regular intervals. if it has the correct amount of chars, I treat it as a successful read.
            • 3. Re: Defining and raising custom events
              ssmiley483 Level 1
              Thanks Production Monkey for the detailed answer and example!! That is very helpful. I'll look into behaviors and parent scripts and see how they all work.
              • 4. Re: Defining and raising custom events
                ssmiley483 Level 1
                matthewmaday,

                I would love to not externalize my scripts, but in this case that's not possible. I'm not doing the UI portion for this project, just building a reusable library that will be integrated into 17 other Director applications by two different organizations.

                My task is to build this library that abstracts away the complexities of getting barcode scans and communicating with a central server.