AppEvents - An easy to use events framework

Hi everyone,

I’m a professional software developer by day (mainly .net) and a hobbyist developer at any other time i can… I thought the best way to introduce myself would be to come bearing gifts of code :smiley:

So here it is AppEvents - a very small framework which lets you simply define events and use them in a flexible way.

For those who aren’t sure what Events are, they are something which allows us to specify a function to call when something is about to happen, is happening or has happened in code, like a button being pressed, or externally like the user touching the screen.

You can create single events or collections of events as fields on your classes which are then consumable in a global context or a more limited/isolated scope.

ExampleEventObject = class()

function ExampleEventObject:init()

          -- globally tracked event
          self.exampleEvent = AppEvents.define("example_event",self)

          -- limited scope / local event
          self.exampleEventLocal = Event("Example_event_local",self)

          -- globally tracked events collection (which can contain multiple events)
 = AppEvents.track(self)
          self.exampleEvent1 ="example_event")

         -- in this context (self.exampleEvent == self.exampleEvent1) = true

         -- limited scope / local events collection
         self.localEvents = Events(self)


function setup()
        obj = ExampleEventObject()


-- handler / callback args can be a fixed number or dynamic 
function example_event(sender,...)
     -- called when "example_event" is raised / triggered

You can also use events in a similar way to the Events class in Cargo-Bot (which was partly my inspiration for this).

ExampleEventObject = class()

function ExampleEventObject:init()

function ExampleEventObject:bindEvents()



function ExampleEventObject:play(sender,val)

I’ve commented the code quite extensively (perhaps even excessively in places) and there lots of examples in Main and ExampleEventsObject so I encourage you to take a look for some more detailed examples!

AppEvents Source:

AppEvents AutoInstall:

Edit: Fixed issue where runtime error messages would be suppressed inside event handlers. Altered to xpcall and print stacktrace if things go wrong :). Also added global to Event to turn off using dispatchers.

Welcome to Codea! Very cool, I’ll have to play around with it when I get home from work :slight_smile: Thanks for sharing it!

Thanks @Briarfox! I’m not sure if this is just my inexperience with AutoGist :slight_smile: but I think I may have stumbled across a bug where if you Gist the project and then delete the repo and then try and Gist it again you get an error asking to reset the token, which I did, but this didn’t resolve it, but the manual gist worked fine :slight_smile: apart from the tab order saved was for AutoGist itself :confused: (which you’ll see from my revisions). But it did help me spot and nail a couple of issues just before posting so it worked out well :smiley:


We likes presents, we does… :slight_smile:

@XanDDemoX!! Welcome and thanks. AppEvents looks very useful, if I can figure out how to use it.

@XanDDemoX - it’s very well documented and professional, thanks for all the effort involved.

I’ve tried to understand exactly what the code is doing, so I’d appreciate your confirmation that essentially, it allows you to define events globally or per object, and raise them, suppress them, etc.

If I were to build this myself, I might set up a simple table of events, each containing a list consisting of an object pointer (nil for global), event name, callback pointer and status text (used for suppressing etc). Then I’d have a couple of functions that added events, changed status, and handled raise requests depending on the status text.

This would be a lot simpler than what you have done, so I’m wondering if I’ve missed something.

I will have a closer look at your gift later. Its 4:55 and I not awake enough …
I still struggle to understand how the cargo bot code handles the events (ticks…).

@XanDDemoX I’ll look into it. It may have saved the tab order on the manual gist beause Gist was the project running, I’ll have to play with it.
Tab order is fixed with manual gist. click update in AutoGist.

Ok to remove a projects saved gistid or set a old gistid.


    a:setKey("gistID") --Sets the gist ID key

    a:deleteProject("project") --Removes all revisions and keys from global save.

Thank you all :D! Essentially yes! It certainly does @Ignatz :slight_smile: and yes a multi dimensional table would be another way of achieving events but it might take away some of the flexibility with setting up and consuming events. I’ve tried to keep calls and function parameters to a minimum to try and keep the interface as simple as possible (one liners as mush as possible) but also trying to leave users free to use it how they like so they can use fields or static functions or a combination to setup their events and then use instance functions, global functions, static functions, or dynamic / lambda functions for their event callbacks :).

I’m certainly not denying it could be compressed down to a smaller solution but I feel this is clearer and easier to setup and use if your new to programming but also powerful enough to satisfy the gurus amongst us too :smiley:

I also forgot to mention a couple of points in my main post: coroutines are used to raise events in Dispatcher, you can inherit both the Event class or the Events class and customise it and still use your custom versions with AppEvents or Events (in the case of the Event class) and this also includes: Tower - a general purpose array manipulation class with .net like functionality and stack, queue and Deque functionality :slight_smile:

@XanDDemoX - thank you for that. I think you’ll find that this is way, way over the heads of beginners, but it should be useful for larger projects where a highly structured approach is needed.

In any event, I am going to look through your code for interesting and useful stuff (eg the Tower class), and I thank you again for going to all that effort.

@Briarfox - Thanks! I’ll give it a go when I’m home!

@Ignatz - I fear you maybe right, perhaps one of your excellent tutorials would help with that :wink: and thank you again its all worth it if even just one person finds it useful :smiley:

@Ric_Esrey and @DaDo - Thanks! If you have any questions then I’m more than happy to answer them :slight_smile: