Skip to content

Instantly share code, notes, and snippets.

@paulhoux
Last active December 20, 2015 00:38
Show Gist options
  • Save paulhoux/6042854 to your computer and use it in GitHub Desktop.
Save paulhoux/6042854 to your computer and use it in GitHub Desktop.
Example of using signals and slots with derived classes. Sample made for Cinder. Simply create an empty Cinder application called "Signals" using TinderBox, then replace the contents of ```SignalsApp.cpp``` with this code.
#define _SCL_SECURE_NO_WARNINGS
#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
using namespace ci;
using namespace ci::app;
using namespace std;
//--------------------------
// Button base class
//--------------------------
class Button
{
public:
Button() : mRect( Rectf(0, 0, 300, 100) ), mIsPressed(false) {}
Button( const Rectf& rect ) : mRect(rect), mIsPressed(false) {}
virtual ~Button() {}
virtual void draw();
virtual void mouseDown( MouseEvent event );
virtual void mouseUp( MouseEvent event );
public:
ci::signals::signal<void( Button& )> sClicked;
private:
bool mIsPressed;
Rectf mRect;
};
void Button::draw()
{
gl::color( mIsPressed ? Color(1, 0, 0) : Color(0, 1, 0) );
gl::drawSolidRect( mRect );
}
void Button::mouseDown( MouseEvent event )
{
mIsPressed = mRect.contains(event.getPos());
}
void Button::mouseUp( MouseEvent event )
{
if (mIsPressed && mRect.contains(event.getPos()))
sClicked(*this);
mIsPressed = false;
}
//--------------------------
// LoginButton derived class
//--------------------------
class LoginButton : public Button
{
public:
LoginButton() : Button( Rectf(0, 150, 300, 250) ) {}
LoginButton( const Rectf& rect ) : Button(rect) {}
~LoginButton() {}
};
//--------------------------
// Application class
//--------------------------
class SignalsApp : public AppNative {
public:
void setup();
void draw();
void mouseDown( MouseEvent event );
void mouseUp( MouseEvent event );
void onButtonClicked( Button& button );
private:
Button mButton;
LoginButton mLoginButton;
};
void SignalsApp::setup()
{
mButton.sClicked.connect( std::bind( &SignalsApp::onButtonClicked, this, std::_1 ) );
mLoginButton.sClicked.connect( std::bind( &SignalsApp::onButtonClicked, this, std::_1 ) );
}
void SignalsApp::draw()
{
gl::clear();
mButton.draw();
mLoginButton.draw();
}
void SignalsApp::mouseDown( MouseEvent event )
{
mButton.mouseDown( event );
mLoginButton.mouseDown( event );
}
void SignalsApp::mouseUp( MouseEvent event )
{
mButton.mouseUp( event );
mLoginButton.mouseUp( event );
}
void SignalsApp::onButtonClicked( Button& button )
{
try {
LoginButton& btn = dynamic_cast<LoginButton&>( button );
console() << "LoginButton clicked" << std::endl;
}
catch( ... /*const std::bad_cast &e*/ ) {
// it didn't work, so it's not a LoginButton
console() << "Button clicked" << std::endl;
}
}
CINDER_APP_NATIVE( SignalsApp, RendererGl )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment