Skip to content
Freeman Zhang edited this page Mar 4, 2016 · 20 revisions

Quick Guide

Build and Installation

You can just drag the source code into your C++ project.

Or use cmake to build a dynamic or static library, just

$ cd <folder where you checkout the source>
$ mkdir build
$ cd build
$ cmake ../
$ make && sudo make install

By default, it will install header files to /usr/local/include, and library binary to /usr/local/lib.

Available cmake options:

  • CMAKE_INSTALL_PREFIX: this is a built-in cmake option, which you can use to specify where to install the headers and library. Default is /usr/local.
  • BUILD_UNIT_TEST: A bool option to compile the unit test code. Default is OFF.
  • WITH_QT5: A bool option to compile test code to compare this project with Qt5 signal-slot. Default: OFF.

Declaring Event

Use the template class CppEvent::Event<> to declare an event. In mose cases, you need to use it as a member variable in your class, you can put it in any area of public, protected, private as you want.

For example, suppose you are developing a GUI project, you may need a clicked event in a button class:

Example 1. Button class with 'clicked' event

class Button: public Widget
{
public:

    Button(Widget* parent);

    // Event connection interface
    inline CppEvent::Event<>& clicked ()
    {return clicked_;}

protected:

    virtual void mousePress (MouseParams const & params);

private:

    // Event implementation
    CppEvent::Event<> clicked_;
};

void Button::mousePress(MouseParams const & params)
{
	// Do sth...
    clicked_.Fire();
}

Note: an event object is not copyable. e.g.

	CppEvent::Event<> event1;
	CppEvent::Event<> event2(event1);	// Error
	CppEvent::Event<> event3;
	event3 = event1;	// Error

Connecting Events

Events can be connected to event handlers. In libCppEvent, event handlers are member functions bound to the specific object. Internally libCppEvent implement delegate in a way inspired by Fast C++ Delegate: Boost.Function 'drop-in' replacement and multicast by JaeWook Choi.

In libCppEvent you cannot connect event to any member function. You can only connect an event to member functions of a CppEvent::Observer or subclass. This design makes sure when the Observer object is deleted, all event connection will be removed safely.

Example

Connection is established by Connect() method of the CppEvent::Event<>. The method requires 2 arguments.

  • A pointer to a CppEvent::Trackable object
  • A pointer to the member function of the receiver object

Example 2. Connect a button to a label widget.

class Widget: public CppEvent::Observer;

class Label: public Widget
{
public:

    Dialog (Widget* parent);

    void OnShowText ();
};

Button* btn = new Button;
Label* lbl = new Label;

btn->clicked().Connect(lbl, &Label::OnShowText);

Disconnecting Events

Use Disconnect method:

	btn->clicked().Disconnect(lbl, &Label::OnShowText);

Arguments

Events can have arbitrary number of arguments. Types of arguments are specified as arguments for template class CppEvent::Event<>.

For example:

	using namespace CppEvent;
	
	Event<Widget* sender, bool toggled> event1;
	Event<const String& str, size_t length> event2;

Observer

You can disconnect the event when being invoked in an observer:

	void Label::OnShowText (Button* sender)
	{
		sender->clicked().Disconnect(this, &Label::OnShowText);
	}

You can delete this when being invoked:

	void Label::OnShowText ()
	{
		delete this;
	}

Multicast

Note: CppEvent::Event<> support multicast, when you fire an event, it will invoke all connected methods.

Example

Event Chaining

A CppEvent::Event<> object can be used as an event handler too, as it's also a trackable object.

Example

Example 4. Event chaining

Button* btn1 = new Button;
Button* btn2 = new Button;

btn1->clicked().Connect(btn2->clicked());

Click btn1 will fire clicked() event in btn2.

Virtual Member Function

Member function which is connected to an event can be virtual and abstract (pure virtual).

Example 5. Connect event to a virtual method

class Widget: public CppEvent::Trackable;

class AbstractDialog: public Widget
{
public:
  AbstractDialog (Widget* parent)
  {
      ok_ = new Button;
      ok->clicked().connect(this, &AbstractDialog::OnShowText);
  }

  virtual void OnShowText () = 0; // pure virtual

private:

  Button* ok_;
};

class Dialog: public AbstractDialog
{
public:
    Dialog (Widget* parent);
    virtual void OnShowText () = override;
};

AbstractDialog *dlg = new Dialog();
btn1->clicked().Connect(dlg, &AbstractDialog::OnShowText);

Complex Example

Example

Advice On Multi-thread Programming

Warning: By default, libCppEvent does not provide any protection in multi-thread environment. You should take care of the racecondition in your code.

TBD