Commit 30eb22b8 authored by Mathias Goldau's avatar Mathias Goldau

[ADD #274] Now WCustomWidget supports event based notification with the use of...

[ADD #274] Now WCustomWidget supports event based notification with the use of member functions given via boost::bind
parent d299dae5
......@@ -26,11 +26,8 @@
#include "WCustomWidget.h"
WCustomWidget::WCustomWidget( std::string title, EventType subscription ):
m_title( title ),
m_eventNotifier( new WCondition() ),
m_events( new WSharedSequenceContainer< EventDeque >() ),
m_subscription( subscription )
WCustomWidget::WCustomWidget( std::string title ):
m_title( title )
{
}
......@@ -42,27 +39,3 @@ std::string WCustomWidget::getTitle() const
{
return m_title;
}
WCustomWidget::EventQueueSPtr WCustomWidget::getNextEvents()
{
EventQueueSPtr unhandledEvents( new EventQueue() );
WSharedSequenceContainer< EventDeque >::WriteTicket t = m_events->getWriteTicket();
while( !t->get().empty() )
{
unhandledEvents->push( t->get().front() );
t->get().pop_front();
}
return unhandledEvents;
}
WCondition::SPtr WCustomWidget::getEventNotifier() const
{
return m_eventNotifier;
}
bool WCustomWidget::newEvents() const
{
WSharedSequenceContainer< EventDeque >::ReadTicket t = m_events->getReadTicket();
return t->get().size() > 0;
}
......@@ -26,40 +26,44 @@
#define WCUSTOMWIDGET_H
#include <string>
#include <queue>
#include <deque>
#include <boost/shared_ptr.hpp>
#include <osg/ref_ptr>
#include "../common/WCondition.h"
#include "../common/WSharedSequenceContainer.h"
#include "../graphicsEngine/WGEViewer.h"
class WGEGroupNode;
/**
* Custom widget which is created by a module to display custom information.
* Is just a short hand to the long name "osgGA::GUIEventAdapter".
*/
class WCustomWidget
class GUIEvents : public osgGA::GUIEventAdapter
{
public:
/**
* Forward EventType from OSG
*/
typedef osgGA::GUIEventAdapter::EventType EventType;
using osgGA::GUIEventAdapter::EventType;
using osgGA::GUIEventAdapter::MouseButtonMask;
using osgGA::GUIEventAdapter::KeySymbol;
using osgGA::GUIEventAdapter::ModKeyMask;
using osgGA::GUIEventAdapter::MouseYOrientation;
using osgGA::GUIEventAdapter::ScrollingMotion;
using osgGA::GUIEventAdapter::TabletPointerType;
private:
/**
* Queue of GUI events.
* The constructor is private to forbid instance generation.
*/
typedef std::queue< osg::ref_ptr< osgGA::GUIEventAdapter > > EventQueue;
GUIEvents()
{
}
};
/**
* Convenience short hand for \c boost::shared_ptr on \c EventQueue.
/**
* Custom widget which is created by a module to display custom information.
*/
typedef boost::shared_ptr< EventQueue > EventQueueSPtr;
class WCustomWidget
{
public:
/**
* Abbreviation for a shared pointer on a instance of this class.
*/
......@@ -74,9 +78,8 @@ public:
* Constructor. Create a custom widget instance.
*
* \param title the title of the widget
* \param subscription Binary mask on which event types you want to be notified.
*/
explicit WCustomWidget( std::string title, EventType subscription = osgGA::GUIEventAdapter::NONE );
explicit WCustomWidget( std::string title );
/**
* Destructor
......@@ -119,114 +122,18 @@ public:
virtual size_t width() const = 0;
/**
* Returns the next unhandled GUI event on this widget. After calling this function you take responisbility on the event-copy,
* (meaning destroy it when you do not need it anymore). Additionally the notification of new events will be triggered again
* in case there are more events waiting to be processed.
* Adds an event handler to the widget's view.
*
* \return Next GUI event ( shallow copy ).
* \param handler Pointer to the handler.
*/
virtual EventQueueSPtr getNextEvents();
/**
* This condition fires whenever a new event has to be handled and there was no old event left.
*
* \return \c WCondition as event notifier.
*/
virtual WCondition::SPtr getEventNotifier() const;
/**
* Determines if there are new events which you have subscribed to and need to be processed or not.
*
* \return True when there are new events, false otherwise.
*/
virtual bool newEvents() const;
virtual void addEventHandler( osgGA::GUIEventHandler* handler ) = 0;
protected:
/**
* \class WindowHandler
*
* An event handler for a custom widget.
*/
class WindowHandler : public osgGA::GUIEventHandler
{
public:
/**
* Constructor.
*
* \param widget The custom widget which should be notified.
*/
explicit WindowHandler( WCustomWidget* widget )
: m_widget( widget )
{
}
/**
* Deals with the events found by the osg.
*
* \param ea Event class for storing Keyboard, mouse and window events.
*
* \return true if the event was handled.
*/
bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& /* aa */ )
{
if( ea.getEventType() & m_widget->m_subscription )
{
WSharedSequenceContainer< EventDeque >::WriteTicket t = m_widget->m_events->getWriteTicket();
if( t->get().size() == 0 ) // when this is the first event, notify module only once
{
m_widget->m_eventNotifier->notify();
}
// else: Do not spam the module for new events, but still collect events into queue. Module will need to make queue empty again
t->get().push_back( new osgGA::GUIEventAdapter( ea ) );
return true;
}
return false; // There was no subscription to this event
}
private:
/**
* Reference to the WCustomWidget which has the condition for such events and needs to be notified.
*/
WCustomWidget* const m_widget;
};
/**
* This is a short hand type for our FiFo queue containing events.
*
* \note A std::queue would be better, as we are using it as a FiFo queue, but inorder to have thread safe access,
* we use WSharedSequenceContainer which only supports deque, list and vector at the moment.
*/
typedef std::deque< osg::ref_ptr< osgGA::GUIEventAdapter > > EventDeque;
/**
* Short hand type for boost::shared_ptr on internal event deque.
*/
typedef boost::shared_ptr< EventDeque > EventDequeSPtr;
private:
/**
* The widget's title string.
*/
std::string m_title;
/**
* Condition fired if an GUI event has occured.
*/
WCondition::SPtr m_eventNotifier;
/**
* Stores last GUI events.
*/
WSharedSequenceContainer< EventDeque >::SPtr m_events;
/**
* Binary mask describing which events should be used for notification. For example you may use:
* \c subscription=MOVE|SCROLL|RESIZE.
*/
EventType m_subscription;
};
#endif // WCUSTOMWIDGET_H
......@@ -42,9 +42,6 @@ WQtCustomDockWidget::WQtCustomDockWidget( std::string title, QWidget* parent, WG
// send mouse move events even if no button is pressed
getGLWidget()->setMouseTracking( true );
// register event handler for updating event condition
getViewer()->getView()->addEventHandler( new WindowHandler( this ) ); // register an event handler to update change conditions and event types
}
osg::ref_ptr< WGEGroupNode > WQtCustomDockWidget::getScene() const
......@@ -83,4 +80,9 @@ size_t WQtCustomDockWidget::width() const
return static_cast< size_t >( getViewer()->getCamera()->getViewport()->width() );
}
void WQtCustomDockWidget::addEventHandler( osgGA::GUIEventHandler* handler )
{
getViewer()->getView()->addEventHandler( handler );
}
......@@ -91,6 +91,11 @@ public:
*/
virtual size_t width() const;
/**
* \copydoc WCustomWidget::addEventHandler()
*/
virtual void addEventHandler( osgGA::GUIEventHandler* handler );
protected:
private:
/**
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment