Newer
Older
Import / research / signals-slots / src / gui / TDT / application.cpp
/*
    3D C++ Toolkit (TDT)
    Application Class
    Copyright (c) 2008
    John Ryland
*/
#include <TDT/application.h>
#include <GLUT/glut.h>
#include <unistd.h>


//#define DEBUG_CALLBACKS(s)      printf(s  "\n")
#define DEBUG_CALLBACKS(s)


namespace TDT
{


static void glutDisplayCallback(void)
{
    DEBUG_CALLBACKS("glutDisplayCallback");
    Application::instance()->dispatchEvent(Event(Event::Paint));
}


static void glutReshapeCallback(int width, int height)
{
    DEBUG_CALLBACKS("glutReshapeCallback");
    Application::instance()->dispatchEvent(Event(Event::Resize, width, height));
}


static void glutKeyboardCallback(unsigned char key, int x, int y)
{
    DEBUG_CALLBACKS("glutKeyboardCallback");
    Application::instance()->dispatchEvent(Event(Event::KeyPress, x, y, key));
} 


static void glutKeyboardUpCallback(unsigned char key, int x, int y)
{
    DEBUG_CALLBACKS("glutKeyboardUpCallback");
    Application::instance()->dispatchEvent(Event(Event::KeyRelease, x, y, key));
}


static void glutMouseCallback(int button, int state, int x, int y)
{
    DEBUG_CALLBACKS("glutMouseCallback");
    if ( state == 0 ) {
        Application::instance()->dispatchEvent(Event(Event::MousePress, x, y, button));
    } else {
        Application::instance()->dispatchEvent(Event(Event::MouseRelease, x, y, button));
    }
}


static void glutMotionCallback(int x, int y)
{
    DEBUG_CALLBACKS("glutMotionCallback");
    Application::instance()->dispatchEvent(Event(Event::MouseMove, x, y));
}


static void glutPassiveMotionCallback(int x, int y)
{
    DEBUG_CALLBACKS("glutPassiveMotionCallback");
    Application::instance()->dispatchEvent(Event(Event::MouseMove, x, y));
}


static void glutEntryCallback(int state)
{
    DEBUG_CALLBACKS("glutEntryCallback");
    if ( state == 0 ) {
        Application::instance()->dispatchEvent(Event(Event::FocusOut));
    } else {
        Application::instance()->dispatchEvent(Event(Event::FocusIn));
    }
}


static void glutVisibilityCallback(int state)
{
    DEBUG_CALLBACKS("glutVisibilityCallback");
    if ( state == 0 ) {
        Application::instance()->dispatchEvent(Event(Event::Hide));
    } else {
        Application::instance()->dispatchEvent(Event(Event::Show));
    }
}


static void glutIdleCallback(void)
{
    DEBUG_CALLBACKS("glutIdleCallback");
    Application::instance()->dispatchEvent(Event(Event::Idle));
}


static void glutTimerCallback(int timerId)
{
    DEBUG_CALLBACKS("glutTimerCallback");
    Application::instance()->dispatchEvent(Event(Event::Timer, timerId));
}


static void glutOverlayDisplayCallback(void)
{
    DEBUG_CALLBACKS("glutOverlayDisplayCallback");
    Application::instance()->dispatchEvent(Event(Event::OverlayDisplay));
}


static void glutCloseCallback(void)
{
    DEBUG_CALLBACKS("glutCloseCallback");
    Application::instance()->dispatchEvent(Event(Event::Close));
}


Application *Application::app = 0;


Application::Application(int argc, char *argv[])
{
    if ( app ) {
        printf("Error: you should only construct one Application instance, typically in main.c\n");
        return;
    } else {
        app = this;
    }

    init(argc, argv);
    installCallbacks();
}


Application::~Application()
{
}


void Application::init(int argc, char *argv[])
{
    glutInit(&argc, argv);
}


void Application::installCallbacks()
{
    glutDisplayFunc(glutDisplayCallback);
    glutReshapeFunc(glutReshapeCallback);
    glutKeyboardFunc(glutKeyboardCallback);
    glutKeyboardUpFunc(glutKeyboardUpCallback);
    glutMouseFunc(glutMouseCallback);
    glutMotionFunc(glutMotionCallback);
    glutPassiveMotionFunc(glutPassiveMotionCallback);
    glutEntryFunc(glutEntryCallback);
    glutVisibilityFunc(glutVisibilityCallback);
    glutIdleFunc(glutIdleCallback);
    glutOverlayDisplayFunc(glutOverlayDisplayCallback);
#if (GLUT_MACOSX_IMPLEMENTATION >= 2)
    glutWMCloseFunc(glutCloseCallback);
#elif defined(FREEGLUT)
    glutCloseFunc(glutCloseCallback);
#endif
}


Application *Application::instance()
{
    if (!app) {
        printf("Warning, it appears that you are calling Application::instance() before constructing one, usually this means a programming error\n");
        new Application(0,0);
    }
    return app; 
}


int Application::exec()
{
    glutMainLoop();
    return 0;
}


void Application::insertWindow(Window *win)
{
    windows.push_back(win);
}


void Application::removeWindow(Window *win)
{
    std::list<Window*>::iterator i = windows.begin();
    while (i != windows.end())
    {
        if (*i == win) {
            windows.erase(i);
            return;
        }
        i++;
    }
}


void Application::addTimer(int milliSec, Window *win)
{
    glutTimerFunc(milliSec, glutTimerCallback, win->winId());
}


bool Application::eventFilter(Event event)
{
    return false;
}


void Application::dispatchEvent(Event event)
{
    if (eventFilter(event))
        return;

    int winId = glutGetWindow();
    std::list<Window*>::iterator i = windows.begin();
    while (i != windows.end())
    {
        if ((*i)->winId() == winId) {
            (*i)->event(event);
            return; /* Assuming that only one window will match the winId */
        }
        i++;
    }
}


};