Ah nice lib!
I like the event based approach and I am working on something similar my self.
I still have to give your lib a thorough look so forgive me if I sound stupid
The event based mechanism solves the spaghetti code problem I see in most project's source code. But I want to go even further. I also want to solve the problem of an LCD library only working when you connect the correct pins or can only handle one or fails when you have shift-registers in your design to save on IO pins.
I am now working on a stream/event bases approach using C++ templates. Because with C++ templates you don't need most virtual (although I love polymorphism) and you dont need to keep reference pointers to event handlers! Try to calculate how many bytes are lost to pointer reference to functions or other objects in your lib!?
Here's what I mean:
// BaseT must implement OnEvent().
template <class BaseT>
class MyEventSource : public BaseT
// some logic to detect events
// call BaseT
That is the core of what I'm doing in my library. It also allows to create your own class hierarchies. Simply typedef your choice of derived template classes. This allows you to mix and match stuff together to get what you want. So now you can use the LCD logic (a template class that makes no assumptions on what pins are used or how the actual hardware is driven) and stack it on a custom class that implements the shifting logic for your shift registers that actually drives the LCD. This solves the problem with the current lib impl's that mix a lot of responsibilities into one class and in doing so killing any flexibility to do things differently.
Another thing I want to solve - which is not hard at all, but creeps in real easy - is that you make classes that do only one thing (touched on this previously). What I mean is for example the serial class. Don't make a class that handles both sending and receiving - instead make 2 classes, one for reading and one for writing. I ran into this when I wanted to make a MIDI project that receives on one MIDI port but sends on 4 ports.
I am at the beginning of creating my lib so there are a lot of problems I will run into and have to find a solution for. And now I will take a look at your work.
EDIT: looking at the lib I would suggest not creating an event for each state (as with the button down-up etc). Instead I would suggest one event that also receives the state of the button. This saves the user of your class a lot of hassle when trying to implement combined logic and it hardly makes detecting a single state harder for the moderate users... Also something I ran into with the MIDI lib that also has separate callback for each type of message. It also wastes a lot of function references eating up memory.
EDIT2: I look at the impl of ButtonEvent. You use dynamic memory allocation to reserve memory for a ButtonInfo struct in the addButton. I am personally trying to avoid any dynamic memory allocation, due to the overhead and the mentioned bugs. Also I do not agree with the notion of that default instance. Its crap. Why not let the use instantiate a ButtonEvent class for each button he/she needs!? Buttons are not usually allocated dynamically ;-) So that will eliminate the need for any dynamic memory allocations. Also try to calculate how much memory is needed by one instance of your class. Its huge (in MCU terms). Do you really need 4 milli second long vars!? Do you think anyone will use a hold timeout of 4 hours!? :-P
Try not take this criticism too personally, just trying to help.