Canvas: support for custom events and event dispatching.
This commit is contained in:
@@ -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}")
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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&,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
18
simgear/canvas/events/CMakeLists.txt
Normal file
18
simgear/canvas/events/CMakeLists.txt
Normal 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}
|
||||
)
|
||||
51
simgear/canvas/events/CustomEvent.cxx
Normal file
51
simgear/canvas/events/CustomEvent.cxx
Normal 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
|
||||
71
simgear/canvas/events/CustomEvent.hxx
Normal file
71
simgear/canvas/events/CustomEvent.hxx
Normal 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_ */
|
||||
70
simgear/canvas/events/MouseEvent.cxx
Normal file
70
simgear/canvas/events/MouseEvent.cxx
Normal 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
|
||||
@@ -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; }
|
||||
36
simgear/canvas/events/event_test.cpp
Normal file
36
simgear/canvas/events/event_test.cpp
Normal 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 );
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user