/* -*-c++-*- Producer - Copyright (C) 2001-2004  Don Burns
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
 */


#ifndef PRODUCER_KEYBOARD_MOUSE
#define PRODUCER_KEYBOARD_MOUSE 1

#include <OpenThreads/Thread>

#include <Producer/Export>
#include <Producer/Referenced>

#include <Producer/Types>
#include <Producer/BlockingQueue>
#include <Producer/RenderSurface>
#include <Producer/InputArea>
#include <Producer/Keyboard>

namespace Producer {

class PR_EXPORT KeyboardMouseCallback : public Referenced 
{
    public :
        KeyboardMouseCallback( ) { }
        enum ScrollingMotion {
            ScrollNone,
            ScrollUp,
            ScrollDown
        };
        virtual void mouseScroll( ScrollingMotion ) {}
        virtual void mouseMotion( float, float) {}
        virtual void passiveMouseMotion( float, float) {}
        virtual void buttonPress( float, float, unsigned int ) {}
        virtual void doubleButtonPress( float, float, unsigned int ) {}
        virtual void buttonRelease( float, float, unsigned int ) {}
        virtual void keyPress( KeyCharacter ) {}
        virtual void keyRelease( KeyCharacter ) {}
        virtual void specialKeyPress( KeyCharacter ) {}
        virtual void specialKeyRelease( KeyCharacter ) {}
        virtual void shutdown() {}
        virtual bool idle() { return false; }
    protected:
        ~KeyboardMouseCallback() {}
};

class PR_EXPORT KeyboardMouse : public Referenced, public OpenThreads::Thread
{
    public :
        KeyboardMouse(Producer::RenderSurface *rs);

        KeyboardMouse(Producer::InputArea *inputArea);
            
        void update(KeyboardMouseCallback &, bool block=false);
            
        void setCallback( KeyboardMouseCallback *cb );
        KeyboardMouseCallback *getCallback() { return _cb.get(); }
            
        void positionPointer( float x, float y );
            
        Producer::RenderSurface *getRenderSurface() { return _rs.get(); }
        const Producer::RenderSurface *getRenderSurface() const { return _rs.get(); }

        Producer::InputArea *getInputArea() { return _inputArea.get(); }
        const Producer::InputArea *getInputArea() const { return _inputArea.get(); }

        /** compute, from normalized mouse coords (x,y) the,  for the specified 
          * RenderSurface, the pixel coordinates (pixel_x,pixel_y). return true 
          * if pixel_x and pixel_y have been successful computed, otherwise return 
          * false with pixel_x and pixel_y left unchanged.*/
        bool computePixelCoords(float x, float y, RenderSurface* rs, float& pixel_x, float& pixel_y); 

    protected:

        virtual ~KeyboardMouse();

        class KeyboardMouseImplementation *_implementation;

        Producer::ref_ptr< Producer::RenderSurface >_rs;
        Producer::ref_ptr< Producer::InputArea >_inputArea;
        Producer::ref_ptr< KeyboardMouseCallback >_cb;
        bool _initialized;
        bool init();
        virtual void run();
};

}
#endif
