Canvas: support for custom events and event dispatching.

This commit is contained in:
Thomas Geymayer
2014-05-18 13:29:48 +02:00
parent 1af6cbc1aa
commit 9c421d55a9
22 changed files with 468 additions and 163 deletions

View File

@@ -12,7 +12,6 @@ set(HEADERS
CanvasPlacement.hxx
CanvasSystemAdapter.hxx
CanvasWindow.hxx
MouseEvent.hxx
ODGauge.hxx
VGInitOperation.hxx
)
@@ -32,5 +31,6 @@ set(SOURCES
add_subdirectory(ShivaVG/src)
add_subdirectory(elements)
add_subdirectory(events)
simgear_scene_component(canvas canvas "${SOURCES}" "${HEADERS}")

View File

@@ -19,8 +19,8 @@
#include "Canvas.hxx"
#include "CanvasEventManager.hxx"
#include "CanvasEventVisitor.hxx"
#include <simgear/canvas/MouseEvent.hxx>
#include <simgear/canvas/CanvasPlacement.hxx>
#include "CanvasPlacement.hxx"
#include <simgear/canvas/events/MouseEvent.hxx>
#include <simgear/scene/util/parse_color.hxx>
#include <simgear/scene/util/RenderConstants.hxx>
@@ -418,7 +418,7 @@ namespace canvas
//----------------------------------------------------------------------------
bool Canvas::handleMouseEvent(const MouseEventPtr& event)
{
if( !_root_group.get() )
if( !_root_group )
return false;
EventVisitor visitor( EventVisitor::TRAVERSE_DOWN,
@@ -430,6 +430,13 @@ namespace canvas
return _event_manager->handleEvent(event, visitor.getPropagationPath());
}
//----------------------------------------------------------------------------
bool Canvas::propagateEvent( EventPtr const& event,
EventPropagationPath const& path )
{
return _event_manager->propagateEvent(event, path);
}
//----------------------------------------------------------------------------
void Canvas::childAdded( SGPropertyNode * parent,
SGPropertyNode * child )

View File

@@ -146,6 +146,8 @@ namespace canvas
SGRect<int> getViewport() const;
bool handleMouseEvent(const MouseEventPtr& event);
bool propagateEvent( EventPtr const& event,
EventPropagationPath const& path );
virtual void childAdded( SGPropertyNode * parent,
SGPropertyNode * child );

View File

@@ -26,6 +26,7 @@ namespace canvas
//----------------------------------------------------------------------------
Event::Event():
type(UNKNOWN),
time(-1),
propagation_stopped(false)
{
@@ -38,7 +39,13 @@ namespace canvas
}
//----------------------------------------------------------------------------
Event::Type Event::getType() const
bool Event::canBubble() const
{
return true;
}
//----------------------------------------------------------------------------
int Event::getType() const
{
return type;
}
@@ -46,14 +53,7 @@ namespace canvas
//----------------------------------------------------------------------------
std::string Event::getTypeString() const
{
switch( type )
{
# define ENUM_MAPPING(name, str) case name: return str;
# include "CanvasEventTypes.hxx"
# undef ENUM_MAPPING
default:
return "unknown";
}
return typeToStr(type);
}
//----------------------------------------------------------------------------
@@ -81,23 +81,57 @@ namespace canvas
}
//----------------------------------------------------------------------------
Event::Type Event::strToType(const std::string& str)
int Event::getOrRegisterType(const std::string& type_str)
{
int type = strToType(type_str);
if( type == UNKNOWN )
{
// Register new type
TypeMap& type_map = getTypeMap();
type = type_map.size() + 1; // ids start with 1 (after UNKNOWN)
type_map.insert(TypeMap::value_type(type_str, type));
}
return type;
}
//----------------------------------------------------------------------------
int Event::strToType(const std::string& str)
{
TypeMap const& type_map = getTypeMap();
TypeMap::map_by<name>::const_iterator it = type_map.by<name>().find(str);
if( it == type_map.by<name>().end() )
return UNKNOWN;
return it->second;
}
//----------------------------------------------------------------------------
std::string Event::typeToStr(int type)
{
TypeMap const& type_map = getTypeMap();
TypeMap::map_by<id>::const_iterator it = type_map.by<id>().find(type);
if( it == type_map.by<id>().end() )
return "unknown";
return it->second;
}
//----------------------------------------------------------------------------
Event::TypeMap& Event::getTypeMap()
{
typedef std::map<std::string, Type> TypeMap;
static TypeMap type_map;
if( type_map.empty() )
{
# define ENUM_MAPPING(type, str) type_map[ str ] = type;
# include "CanvasEventTypes.hxx"
# undef ENUM_MAPPING
# define ENUM_MAPPING(type, str)\
type_map.insert(TypeMap::value_type(str, type));
# include "CanvasEventTypes.hxx"
# undef ENUM_MAPPING
}
TypeMap::const_iterator it = type_map.find(str);
if( it == type_map.end() )
return UNKNOWN;
return it->second;
return type_map;
}
} // namespace canvas

View File

@@ -20,13 +20,15 @@
#define CANVAS_EVENT_HXX_
#include "canvas_fwd.hxx"
#include <boost/bimap.hpp>
namespace simgear
{
namespace canvas
{
class Event
class Event:
public SGReferenced
{
public:
@@ -36,11 +38,11 @@ namespace canvas
# define ENUM_MAPPING(name, str) name,
# include "CanvasEventTypes.hxx"
# undef ENUM_MAPPING
USER_TYPE ///<! first unused id to be used for user defined types (not
/// implemented yet)
CUSTOM_EVENT ///<! all user defined event types share the same id. They
/// are just differentiated by using the type string.
};
Type type;
int type;
ElementWeakPtr target,
current_target;
double time;
@@ -52,7 +54,19 @@ namespace canvas
// of the actual event instances.
virtual ~Event();
Type getType() const;
/**
* Get whether this events support bubbling
*/
virtual bool canBubble() const;
/**
* Set type of event.
*
* If no such type exists it is registered.
*/
void setType(const std::string& type);
int getType() const;
std::string getTypeString() const;
ElementWeakPtr getTarget() const;
@@ -62,7 +76,19 @@ namespace canvas
void stopPropagation();
static Type strToType(const std::string& str);
static int getOrRegisterType(const std::string& type);
static int strToType(const std::string& type);
static std::string typeToStr(int type);
protected:
struct name {};
struct id {};
typedef boost::bimaps::bimap<
boost::bimaps::tagged<std::string, name>,
boost::bimaps::tagged<int, id>
> TypeMap;
static TypeMap& getTypeMap();
};

View File

@@ -17,7 +17,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include "CanvasEventManager.hxx"
#include "MouseEvent.hxx"
#include <simgear/canvas/events/MouseEvent.hxx>
#include <simgear/canvas/elements/CanvasElement.hxx>
#include <cmath>
@@ -144,6 +144,71 @@ namespace canvas
return handled | propagateEvent(event, path);
}
//----------------------------------------------------------------------------
bool EventManager::propagateEvent( const EventPtr& event,
const EventPropagationPath& path )
{
event->target = path.back().element;
MouseEventPtr mouse_event = dynamic_cast<MouseEvent*>(event.get());
// Event propagation similar to DOM Level 3 event flow:
// http://www.w3.org/TR/DOM-Level-3-Events/#event-flow
// Position update only needed for drag event (as event needs to be
// delivered to element of initial mousedown, but with update positions)
if( mouse_event && mouse_event->type == MouseEvent::DRAG )
{
osg::Vec2f local_pos = mouse_event->client_pos;
// Capturing phase (currently just update position)
for( EventPropagationPath::const_iterator it = path.begin();
it != path.end();
++it )
{
ElementPtr el = it->element.lock();
if( !el )
continue;
it->local_pos = local_pos = el->posToLocal(local_pos);
}
}
bool const do_bubble = event->canBubble();
// Bubbling phase
for( EventPropagationPath::const_reverse_iterator
it = path.rbegin();
it != path.rend();
++it )
{
ElementPtr el = it->element.lock();
if( !el )
{
// Ignore element if it has been destroyed while traversing the event
// (eg. removed by another event handler)
if( do_bubble )
continue;
else
break;
}
// TODO provide functions to convert delta to local coordinates on demand.
// Maybe also provide a clone method for events as local coordinates
// might differ between different elements receiving the same event.
if( mouse_event )
mouse_event->local_pos = it->local_pos;
event->current_target = el;
el->handleEvent(event);
if( event->propagation_stopped || !do_bubble )
return true;
}
return true;
}
//----------------------------------------------------------------------------
bool EventManager::handleClick( const MouseEventPtr& event,
const EventPropagationPath& path )
@@ -249,84 +314,6 @@ namespace canvas
return handled;
}
//----------------------------------------------------------------------------
bool EventManager::propagateEvent( const EventPtr& event,
const EventPropagationPath& path )
{
event->target = path.back().element;
MouseEventPtr mouse_event = boost::dynamic_pointer_cast<MouseEvent>(event);
// Event propagation similar to DOM Level 3 event flow:
// http://www.w3.org/TR/DOM-Level-3-Events/#event-flow
// Position update only needed for drag event (as event needs to be
// delivered to element of initial mousedown, but with update positions)
if( mouse_event && mouse_event->type == MouseEvent::DRAG )
{
osg::Vec2f local_pos = mouse_event->client_pos;
// Capturing phase (currently just update position)
for( EventPropagationPath::const_iterator it = path.begin();
it != path.end();
++it )
{
ElementPtr el = it->element.lock();
if( !el )
continue;
it->local_pos = local_pos = el->posToLocal(local_pos);
}
}
// Check if event supports bubbling
const Event::Type types_no_bubbling[] = {
Event::MOUSE_ENTER,
Event::MOUSE_LEAVE,
};
const size_t num_types_no_bubbling = sizeof(types_no_bubbling)
/ sizeof(types_no_bubbling[0]);
bool do_bubble = true;
for( size_t i = 0; i < num_types_no_bubbling; ++i )
if( event->type == types_no_bubbling[i] )
{
do_bubble = false;
break;
}
// Bubbling phase
for( EventPropagationPath::const_reverse_iterator
it = path.rbegin();
it != path.rend();
++it )
{
ElementPtr el = it->element.lock();
if( !el )
{
// Ignore element if it has been destroyed while traversing the event
// (eg. removed by another event handler)
if( do_bubble )
continue;
else
break;
}
// TODO provide functions to convert delta to local coordinates on demand.
// Maybe also provide a clone method for events as local coordinates
// might differ between different elements receiving the same event.
if( mouse_event )
mouse_event->local_pos = it->local_pos;
event->current_target = el;
el->handleEvent(event);
if( event->propagation_stopped || !do_bubble )
return true;
}
return true;
}
//----------------------------------------------------------------------------
bool
EventManager::checkClickDistance( const osg::Vec2f& pos1,

View File

@@ -33,8 +33,14 @@ namespace canvas
// Used as storage by EventManager during event propagation
mutable osg::Vec2f local_pos;
EventTarget( Element* el,
const osg::Vec2f pos = osg::Vec2f() ):
element(el),
local_pos(pos)
{}
};
typedef std::deque<EventTarget> EventPropagationPath;
inline bool operator==(const EventTarget& t1, const EventTarget& t2)
{
return t1.element.lock() == t2.element.lock();
@@ -48,6 +54,9 @@ namespace canvas
bool handleEvent( const MouseEventPtr& event,
const EventPropagationPath& path );
bool propagateEvent( const EventPtr& event,
const EventPropagationPath& path );
protected:
struct StampedPropagationPath
{
@@ -89,9 +98,6 @@ namespace canvas
bool handleMove( const MouseEventPtr& event,
const EventPropagationPath& path );
bool propagateEvent( const EventPtr& event,
const EventPropagationPath& path );
/**
* Check if two click events (either mousedown/up or two consecutive
* clicks) are inside a maximum distance to still create a click or

View File

@@ -34,10 +34,7 @@ namespace canvas
_root(root)
{
if( mode == TRAVERSE_DOWN )
{
EventTarget target = {ElementWeakPtr(), pos};
_target_path.push_back(target);
}
_target_path.push_back( EventTarget(NULL, pos) );
}
//----------------------------------------------------------------------------
@@ -72,8 +69,7 @@ namespace canvas
&& !el.hitBound(_target_path.front().local_pos, pos, local_pos) )
return false;
EventTarget target = {ElementPtr(&el), local_pos};
_target_path.push_back(target);
_target_path.push_back( EventTarget(&el, local_pos) );
if( el.traverse(*this) || &el == _root.get() )
return true;

View File

@@ -21,7 +21,7 @@
#include "Canvas.hxx"
#include "CanvasObjectPlacement.hxx"
#include "MouseEvent.hxx"
#include <simgear/canvas/events/MouseEvent.hxx>
#include <simgear/props/props.hxx>
#include <simgear/scene/util/SGPickCallback.hxx>

View File

@@ -20,7 +20,7 @@
#define CANVAS_WINDOW_HXX_
#include <simgear/canvas/elements/CanvasImage.hxx>
#include <simgear/canvas/MouseEvent.hxx>
#include <simgear/canvas/events/MouseEvent.hxx>
#include <simgear/props/PropertyBasedElement.hxx>
#include <simgear/props/propertyObject.hxx>
#include <simgear/misc/CSSBorder.hxx>

View File

@@ -51,6 +51,10 @@ namespace canvas
SG_FWD_DECL(Text)
SG_FWD_DECL(Window)
SG_FWD_DECL(Event)
SG_FWD_DECL(CustomEvent)
SG_FWD_DECL(MouseEvent)
#undef SG_FWD_DECL
#define SG_FWD_DECL(name)\
@@ -58,8 +62,6 @@ namespace canvas
typedef boost::shared_ptr<name> name##Ptr;\
typedef boost::weak_ptr<name> name##WeakPtr;
SG_FWD_DECL(Event)
SG_FWD_DECL(MouseEvent)
SG_FWD_DECL(Placement)
SG_FWD_DECL(SystemAdapter)
@@ -68,6 +70,9 @@ namespace canvas
class EventManager;
class EventVisitor;
struct EventTarget;
typedef std::deque<EventTarget> EventPropagationPath;
typedef std::map<std::string, const SGPropertyNode*> Style;
typedef ElementPtr (*ElementFactory)( const CanvasWeakPtr&,
const SGPropertyNode_ptr&,

View File

@@ -17,8 +17,9 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include "CanvasElement.hxx"
#include <simgear/canvas/Canvas.hxx>
#include <simgear/canvas/CanvasEventVisitor.hxx>
#include <simgear/canvas/MouseEvent.hxx>
#include <simgear/canvas/events/MouseEvent.hxx>
#include <simgear/math/SGMisc.hxx>
#include <simgear/misc/strutils.hxx>
#include <simgear/scene/material/parseBlendFunc.hxx>
@@ -211,17 +212,7 @@ namespace canvas
"addEventListener(" << _node->getPath() << ", " << type_str << ")"
);
Event::Type type = Event::strToType(type_str);
if( type == Event::UNKNOWN )
{
SG_LOG( SG_GENERAL,
SG_WARN,
"addEventListener: Unknown event type " << type_str );
return false;
}
_listener[ type ].push_back(cb);
_listener[ Event::getOrRegisterType(type_str) ].push_back(cb);
return true;
}
@@ -255,7 +246,7 @@ namespace canvas
}
//----------------------------------------------------------------------------
bool Element::handleEvent(canvas::EventPtr event)
bool Element::handleEvent(EventPtr event)
{
ListenerMap::iterator listeners = _listener.find(event->getType());
if( listeners == _listener.end() )
@@ -267,6 +258,24 @@ namespace canvas
return true;
}
//----------------------------------------------------------------------------
bool Element::dispatchEvent(EventPtr event)
{
EventPropagationPath path;
path.push_back( EventTarget(this) );
for( Element* parent = _parent;
parent != NULL;
parent = parent->_parent )
path.push_front( EventTarget(parent) );
CanvasPtr canvas = _canvas.lock();
if( !canvas )
return false;
return canvas->propagateEvent(event, path);
}
//----------------------------------------------------------------------------
bool Element::hitBound( const osg::Vec2f& global_pos,
const osg::Vec2f& parent_pos,

View File

@@ -108,7 +108,8 @@ namespace canvas
virtual bool ascend(EventVisitor& visitor);
virtual bool traverse(EventVisitor& visitor);
virtual bool handleEvent(canvas::EventPtr event);
virtual bool handleEvent(EventPtr event);
bool dispatchEvent(EventPtr event);
/**
*
@@ -233,7 +234,7 @@ namespace canvas
RelativeScissor *_scissor;
typedef std::vector<EventListener> Listener;
typedef std::map<Event::Type, Listener> ListenerMap;
typedef std::map<int, Listener> ListenerMap;
ListenerMap _listener;

View File

@@ -22,7 +22,7 @@
#include "CanvasPath.hxx"
#include "CanvasText.hxx"
#include <simgear/canvas/CanvasEventVisitor.hxx>
#include <simgear/canvas/MouseEvent.hxx>
#include <simgear/canvas/events/MouseEvent.hxx>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>

View File

@@ -21,7 +21,7 @@
#include <simgear/canvas/Canvas.hxx>
#include <simgear/canvas/CanvasMgr.hxx>
#include <simgear/canvas/CanvasSystemAdapter.hxx>
#include <simgear/canvas/MouseEvent.hxx>
#include <simgear/canvas/events/MouseEvent.hxx>
#include <simgear/scene/util/OsgMath.hxx>
#include <simgear/scene/util/parse_color.hxx>
#include <simgear/misc/sg_path.hxx>
@@ -449,7 +449,7 @@ namespace canvas
if( !src_canvas )
return handled;
MouseEventPtr mouse_event = boost::dynamic_pointer_cast<MouseEvent>(event);
MouseEventPtr mouse_event = dynamic_cast<MouseEvent*>(event.get());
if( mouse_event )
{
mouse_event.reset( new MouseEvent(*mouse_event) );
@@ -473,9 +473,11 @@ namespace canvas
mouse_event->client_pos.x() *= src_canvas->getViewWidth() / size.x();
mouse_event->client_pos.y() *= src_canvas->getViewHeight()/ size.y();
mouse_event->local_pos = mouse_event->client_pos;
handled |= src_canvas->handleMouseEvent(mouse_event);
}
return handled | src_canvas->handleMouseEvent(mouse_event);
return handled;
}
//----------------------------------------------------------------------------

View File

@@ -0,0 +1,18 @@
include (SimGearComponent)
set(HEADERS
CustomEvent.hxx
MouseEvent.hxx
)
set(SOURCES
CustomEvent.cxx
MouseEvent.cxx
)
simgear_scene_component(canvas-events canvas/events "${SOURCES}" "${HEADERS}")
add_boost_test(canvas_event
SOURCES event_test.cpp
LIBRARIES ${TEST_LIBS}
)

View File

@@ -0,0 +1,51 @@
// Canvas user defined event
//
// Copyright (C) 2014 Thomas Geymayer <tomgey@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include "CustomEvent.hxx"
namespace simgear
{
namespace canvas
{
//----------------------------------------------------------------------------
CustomEvent::CustomEvent( std::string const& type_str,
StringMap const& data ):
detail(data)
{
type = getOrRegisterType(type_str);
}
//----------------------------------------------------------------------------
CustomEvent::CustomEvent( int type_id,
StringMap const& data ):
detail(data)
{
type = type_id;
// TypeMap::map_by<id>::type const& type_map = getTypeMap().by<id>();
// assert( type_map.find(type_id) != type_map.end() );
}
//----------------------------------------------------------------------------
void CustomEvent::setDetail(StringMap const& data)
{
detail = data;
}
} // namespace canvas
} // namespace simgear

View File

@@ -0,0 +1,71 @@
///@file Canvas user defined event
//
// Copyright (C) 2014 Thomas Geymayer <tomgey@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#ifndef CANVAS_CUSTOM_EVENT_HXX_
#define CANVAS_CUSTOM_EVENT_HXX_
#include <simgear/canvas/CanvasEvent.hxx>
#include <simgear/structure/map.hxx>
namespace simgear
{
namespace canvas
{
class CustomEvent:
public Event
{
public:
/**
*
* @param type_str Event type name (if name does not exist yet it will
* be registered as new event type)
* @param data Optional user data stored in event
*/
CustomEvent( std::string const& type_str,
StringMap const& data = StringMap() );
/**
*
* @param type_id Event type id
* @param data Optional user data stored in event
*/
CustomEvent( int type_id,
StringMap const& data = StringMap() );
/**
* Set user data
*/
void setDetail(StringMap const& data);
/**
* Get user data
*/
StringMap const& getDetail() const { return detail; }
virtual bool canBubble() const { return bubbles; }
StringMap detail; //<! user data map
bool bubbles;
};
} // namespace canvas
} // namespace simgear
#endif /* CANVAS_CUSTOM_EVENT_HXX_ */

View File

@@ -0,0 +1,70 @@
// Mouse event
//
// Copyright (C) 2014 Thomas Geymayer <tomgey@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include "MouseEvent.hxx"
namespace simgear
{
namespace canvas
{
//----------------------------------------------------------------------------
MouseEvent::MouseEvent():
button(0),
buttons(0),
modifiers(0),
click_count(0)
{
}
//----------------------------------------------------------------------------
MouseEvent::MouseEvent(const osgGA::GUIEventAdapter& ea):
button(0),
buttons(ea.getButtonMask()),
modifiers(ea.getModKeyMask()),
click_count(0)
{
time = ea.getTime();
// Convert button mask to index
int button_mask = ea.getButton();
while( (button_mask >>= 1) > 0 )
button += 1;
}
//----------------------------------------------------------------------------
bool MouseEvent::canBubble() const
{
// Check if event supports bubbling
const Event::Type types_no_bubbling[] = {
Event::MOUSE_ENTER,
Event::MOUSE_LEAVE,
};
const size_t num_types_no_bubbling = sizeof(types_no_bubbling)
/ sizeof(types_no_bubbling[0]);
for( size_t i = 0; i < num_types_no_bubbling; ++i )
if( type == types_no_bubbling[i] )
return false;
return true;
}
} // namespace canvas
} // namespace simgear

View File

@@ -1,4 +1,4 @@
// Mouse event
///@file Mouse event
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -19,7 +19,7 @@
#ifndef CANVAS_MOUSE_EVENT_HXX_
#define CANVAS_MOUSE_EVENT_HXX_
#include "CanvasEvent.hxx"
#include <simgear/canvas/CanvasEvent.hxx>
#include <osgGA/GUIEventAdapter>
namespace simgear
@@ -31,26 +31,10 @@ namespace canvas
public Event
{
public:
MouseEvent():
button(0),
buttons(0),
modifiers(0),
click_count(0)
{}
MouseEvent();
MouseEvent(const osgGA::GUIEventAdapter& ea);
MouseEvent(const osgGA::GUIEventAdapter& ea):
button(0),
buttons(ea.getButtonMask()),
modifiers(ea.getModKeyMask()),
click_count(0)
{
time = ea.getTime();
// Convert button mask to index
int button_mask = ea.getButton();
while( (button_mask >>= 1) > 0 )
button += 1;
}
virtual bool canBubble() const;
osg::Vec2f getScreenPos() const { return screen_pos; }
osg::Vec2f getClientPos() const { return client_pos; }

View File

@@ -0,0 +1,36 @@
/// Unit tests for reference counting and smart pointer classes
#define BOOST_TEST_MODULE structure
#include <BoostTestTargetConfig.h>
#include "MouseEvent.hxx"
#include "CustomEvent.hxx"
namespace sc = simgear::canvas;
BOOST_AUTO_TEST_CASE( canvas_event_types )
{
// Register type
BOOST_REQUIRE_EQUAL( sc::Event::strToType("test"),
sc::Event::UNKNOWN );
BOOST_REQUIRE_EQUAL( sc::Event::getOrRegisterType("test"),
sc::Event::CUSTOM_EVENT );
BOOST_REQUIRE_EQUAL( sc::Event::strToType("test"),
sc::Event::CUSTOM_EVENT );
BOOST_REQUIRE_EQUAL( sc::Event::typeToStr(sc::Event::CUSTOM_EVENT),
"test" );
// Basic internal type
BOOST_REQUIRE_EQUAL( sc::Event::typeToStr(sc::Event::MOUSE_DOWN),
"mousedown" );
BOOST_REQUIRE_EQUAL( sc::Event::strToType("mousedown"),
sc::Event::MOUSE_DOWN );
// Unknown type
BOOST_REQUIRE_EQUAL( sc::Event::typeToStr(123),
"unknown" );
// Register type through custom event instance
sc::CustomEvent e("blub");
BOOST_REQUIRE_EQUAL( e.getTypeString(), "blub" );
BOOST_REQUIRE_NE( e.getType(), sc::Event::UNKNOWN );
}

View File

@@ -33,7 +33,7 @@ namespace simgear
Map() {}
/**
* Initilize a new mape with the given key/value pair.
* Initialize a new map with the given key/value pair.
*/
Map(const Key& key, const Value& value)
{