Canvas: Prepare for DOM Level 2 like event model.
This commit is contained in:
@@ -3,6 +3,10 @@ include (SimGearComponent)
|
||||
set(HEADERS
|
||||
canvas_fwd.hxx
|
||||
Canvas.hxx
|
||||
CanvasEvent.hxx
|
||||
CanvasEventListener.hxx
|
||||
CanvasEventTypes.hxx
|
||||
CanvasEventVisitor.hxx
|
||||
CanvasMgr.hxx
|
||||
CanvasPlacement.hxx
|
||||
CanvasSystemAdapter.hxx
|
||||
@@ -13,6 +17,10 @@ set(HEADERS
|
||||
|
||||
set(SOURCES
|
||||
Canvas.cxx
|
||||
Canvas.cxx
|
||||
CanvasEvent.cxx
|
||||
CanvasEventListener.cxx
|
||||
CanvasEventVisitor.cxx
|
||||
CanvasMgr.cxx
|
||||
CanvasPlacement.cxx
|
||||
ODGauge.cxx
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
#include "Canvas.hxx"
|
||||
#include "CanvasEventVisitor.hxx"
|
||||
#include <simgear/canvas/MouseEvent.hxx>
|
||||
#include <simgear/canvas/CanvasPlacement.hxx>
|
||||
#include <simgear/scene/util/parse_color.hxx>
|
||||
@@ -324,23 +325,31 @@ namespace canvas
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Canvas::handleMouseEvent(const MouseEvent& event)
|
||||
bool Canvas::handleMouseEvent(const MouseEventPtr& event)
|
||||
{
|
||||
_mouse_x = event.x;
|
||||
_mouse_y = event.y;
|
||||
_mouse_dx = event.dx;
|
||||
_mouse_dy = event.dy;
|
||||
_mouse_button = event.button;
|
||||
_mouse_state = event.state;
|
||||
_mouse_mod = event.mod;
|
||||
_mouse_scroll = event.scroll;
|
||||
_mouse_x = event->pos.x();
|
||||
_mouse_y = event->pos.y();
|
||||
_mouse_dx = event->delta.x();
|
||||
_mouse_dy = event->delta.y();
|
||||
_mouse_button = event->button;
|
||||
_mouse_state = event->state;
|
||||
_mouse_mod = event->mod;
|
||||
//_mouse_scroll = event.scroll;
|
||||
// Always set event type last because all listeners are attached to it
|
||||
_mouse_event = event.type;
|
||||
_mouse_event = event->type;
|
||||
|
||||
if( _root_group.get() )
|
||||
return _root_group->handleMouseEvent(event);
|
||||
else
|
||||
if( !_root_group.get() )
|
||||
return false;
|
||||
|
||||
EventVisitor visitor( EventVisitor::TRAVERSE_DOWN,
|
||||
event->getPos(),
|
||||
event->getDelta() );
|
||||
if( !_root_group->accept(visitor) )
|
||||
return false;
|
||||
|
||||
// TODO create special events like click/dblclick etc.
|
||||
|
||||
return visitor.propagateEvent(event);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace canvas
|
||||
void setViewWidth(int w);
|
||||
void setViewHeight(int h);
|
||||
|
||||
bool handleMouseEvent(const MouseEvent& event);
|
||||
bool handleMouseEvent(const MouseEventPtr& event);
|
||||
|
||||
virtual void childAdded( SGPropertyNode * parent,
|
||||
SGPropertyNode * child );
|
||||
|
||||
59
simgear/canvas/CanvasEvent.cxx
Normal file
59
simgear/canvas/CanvasEvent.cxx
Normal file
@@ -0,0 +1,59 @@
|
||||
// Canvas Event for event model similar to DOM Level 2 Event Model
|
||||
//
|
||||
// Copyright (C) 2012 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 "CanvasEvent.hxx"
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
namespace canvas
|
||||
{
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Event::Event():
|
||||
type(UNKNOWN)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Event::Type Event::getType() const
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ElementWeakPtr Event::getTarget() const
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
} // namespace canvas
|
||||
} // namespace simgear
|
||||
56
simgear/canvas/CanvasEvent.hxx
Normal file
56
simgear/canvas/CanvasEvent.hxx
Normal file
@@ -0,0 +1,56 @@
|
||||
// Canvas Event for event model similar to DOM Level 2 Event Model
|
||||
//
|
||||
// Copyright (C) 2012 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_EVENT_HXX_
|
||||
#define CANVAS_EVENT_HXX_
|
||||
|
||||
#include "canvas_fwd.hxx"
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
namespace canvas
|
||||
{
|
||||
|
||||
struct Event
|
||||
{
|
||||
public:
|
||||
|
||||
enum Type
|
||||
{
|
||||
UNKNOWN,
|
||||
# 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)
|
||||
};
|
||||
|
||||
Type type;
|
||||
ElementWeakPtr target;
|
||||
|
||||
Event();
|
||||
Type getType() const;
|
||||
std::string getTypeString() const;
|
||||
ElementWeakPtr getTarget() const;
|
||||
|
||||
};
|
||||
|
||||
} // namespace canvas
|
||||
} // namespace simgear
|
||||
|
||||
#endif /* CANVAS_EVENT_HXX_ */
|
||||
66
simgear/canvas/CanvasEventListener.cxx
Normal file
66
simgear/canvas/CanvasEventListener.cxx
Normal file
@@ -0,0 +1,66 @@
|
||||
// Listener for canvas (GUI) events being passed to a Nasal function/code
|
||||
//
|
||||
// Copyright (C) 2012 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 "CanvasEventListener.hxx"
|
||||
#include "CanvasSystemAdapter.hxx"
|
||||
|
||||
#include <simgear/nasal/nasal.h>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
namespace canvas
|
||||
{
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
EventListener::EventListener(naRef code, const SystemAdapterPtr& sys_adapter):
|
||||
_code(code),
|
||||
_gc_key(-1),
|
||||
_sys(sys_adapter)
|
||||
{
|
||||
assert( sys_adapter );
|
||||
if( !naIsCode(code)
|
||||
&& !naIsCCode(code)
|
||||
&& !naIsFunc(code) )
|
||||
throw std::runtime_error
|
||||
(
|
||||
"canvas::EventListener: invalid function argument"
|
||||
);
|
||||
|
||||
_gc_key = sys_adapter->gcSave(_code);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
EventListener::~EventListener()
|
||||
{
|
||||
assert( !_sys.expired() );
|
||||
_sys.lock()->gcRelease(_gc_key);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void EventListener::call()
|
||||
{
|
||||
const size_t num_args = 1;
|
||||
naRef args[num_args] = {
|
||||
naNil()
|
||||
};
|
||||
_sys.lock()->callMethod(_code, naNil(), num_args, args, naNil());
|
||||
}
|
||||
|
||||
|
||||
} // namespace canvas
|
||||
} // namespace simgear
|
||||
48
simgear/canvas/CanvasEventListener.hxx
Normal file
48
simgear/canvas/CanvasEventListener.hxx
Normal file
@@ -0,0 +1,48 @@
|
||||
// Listener for canvas (GUI) events being passed to a Nasal function/code
|
||||
//
|
||||
// Copyright (C) 2012 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_EVENT_LISTENER_HXX_
|
||||
#define CANVAS_EVENT_LISTENER_HXX_
|
||||
|
||||
#include "canvas_fwd.hxx"
|
||||
#include <simgear/nasal/naref.h>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
namespace canvas
|
||||
{
|
||||
|
||||
class EventListener
|
||||
{
|
||||
public:
|
||||
EventListener( naRef code,
|
||||
const SystemAdapterPtr& sys_adapter );
|
||||
~EventListener();
|
||||
|
||||
void call();
|
||||
|
||||
protected:
|
||||
naRef _code;
|
||||
int _gc_key;
|
||||
SystemAdapterWeakPtr _sys;
|
||||
};
|
||||
|
||||
} // namespace canvas
|
||||
} // namespace simgear
|
||||
|
||||
#endif /* CANVAS_EVENT_LISTENER_HXX_ */
|
||||
31
simgear/canvas/CanvasEventTypes.hxx
Normal file
31
simgear/canvas/CanvasEventTypes.hxx
Normal file
@@ -0,0 +1,31 @@
|
||||
// Mapping between canvas gui Event types and their names
|
||||
//
|
||||
// Copyright (C) 2012 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 ENUM_MAPPING
|
||||
# error "Don't include this file directly!"
|
||||
#endif
|
||||
|
||||
ENUM_MAPPING(MOUSE_DOWN, "mousedown")
|
||||
ENUM_MAPPING(MOUSE_UP, "mouseup")
|
||||
ENUM_MAPPING(CLICK, "click")
|
||||
ENUM_MAPPING(DBL_CLICK, "dblclick")
|
||||
ENUM_MAPPING(MOUSE_MOVE, "mousemove")
|
||||
ENUM_MAPPING(MOUSE_OVER, "mouseover")
|
||||
ENUM_MAPPING(MOUSE_OUT, "mouseout")
|
||||
ENUM_MAPPING(MOUSE_ENTER, "mouseenter")
|
||||
ENUM_MAPPING(MOUSE_LEAVE, "mouseleave")
|
||||
113
simgear/canvas/CanvasEventVisitor.cxx
Normal file
113
simgear/canvas/CanvasEventVisitor.cxx
Normal file
@@ -0,0 +1,113 @@
|
||||
// Visitor for traversing a canvas element hierarchy similar to the traversal
|
||||
// of the DOM Level 2 Event Model
|
||||
//
|
||||
// Copyright (C) 2012 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 "CanvasEvent.hxx"
|
||||
#include "CanvasEventVisitor.hxx"
|
||||
#include <simgear/canvas/elements/CanvasElement.hxx>
|
||||
#include <iostream>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
namespace canvas
|
||||
{
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
EventVisitor::EventVisitor( TraverseMode mode,
|
||||
const osg::Vec2f& pos,
|
||||
const osg::Vec2f& delta ):
|
||||
_traverse_mode( mode )
|
||||
{
|
||||
if( mode == TRAVERSE_DOWN )
|
||||
{
|
||||
EventTarget target = {0, pos, delta};
|
||||
_target_path.push_back(target);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
EventVisitor::~EventVisitor()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool EventVisitor::traverse(Element& el)
|
||||
{
|
||||
if( _traverse_mode == TRAVERSE_UP )
|
||||
return el.ascend(*this);
|
||||
else
|
||||
return el.traverse(*this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool EventVisitor::apply(Element& el)
|
||||
{
|
||||
// We only need to check for hits while traversing down
|
||||
if( _traverse_mode == TRAVERSE_DOWN )
|
||||
{
|
||||
// Transform event to local coordinates
|
||||
const osg::Matrix& m = el.getMatrixTransform()->getInverseMatrix();
|
||||
const osg::Vec2f& pos = _target_path.back().local_pos;
|
||||
const osg::Vec2f local_pos
|
||||
(
|
||||
m(0, 0) * pos[0] + m(1, 0) * pos[1] + m(3, 0),
|
||||
m(0, 1) * pos[0] + m(1, 1) * pos[1] + m(3, 1)
|
||||
);
|
||||
|
||||
if( !el.hitBound(local_pos) )
|
||||
return false;
|
||||
|
||||
const osg::Vec2f& delta = _target_path.back().local_delta;
|
||||
const osg::Vec2f local_delta
|
||||
(
|
||||
m(0, 0) * delta[0] + m(1, 0) * delta[1],
|
||||
m(0, 1) * delta[0] + m(1, 1) * delta[1]
|
||||
);
|
||||
|
||||
EventTarget target = {&el, local_pos, local_delta};
|
||||
_target_path.push_back(target);
|
||||
|
||||
if( el.traverse(*this) )
|
||||
return true;
|
||||
|
||||
_target_path.pop_back();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return el.ascend(*this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool EventVisitor::propagateEvent(const EventPtr& event)
|
||||
{
|
||||
// std::cout << "Propagate event " << event->getTypeString() << "\n";
|
||||
// for( EventTargets::iterator it = _target_path.begin();
|
||||
// it != _target_path.end();
|
||||
// ++it )
|
||||
// {
|
||||
// if( it->element )
|
||||
// std::cout << it->element->getProps()->getPath() << " "
|
||||
// << "(" << it->local_pos.x() << "|" << it->local_pos.y() << ")\n";
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace canvas
|
||||
} // namespace simgear
|
||||
67
simgear/canvas/CanvasEventVisitor.hxx
Normal file
67
simgear/canvas/CanvasEventVisitor.hxx
Normal file
@@ -0,0 +1,67 @@
|
||||
// Visitor for traversing a canvas element hierarchy similar to the traversal
|
||||
// of the DOM Level 2 Event Model
|
||||
//
|
||||
// Copyright (C) 2012 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_EVENT_VISITOR_HXX_
|
||||
#define CANVAS_EVENT_VISITOR_HXX_
|
||||
|
||||
#include "canvas_fwd.hxx"
|
||||
#include <deque>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
namespace canvas
|
||||
{
|
||||
|
||||
class EventVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
enum TraverseMode
|
||||
{
|
||||
TRAVERSE_UP,
|
||||
TRAVERSE_DOWN
|
||||
};
|
||||
|
||||
EventVisitor( TraverseMode mode,
|
||||
const osg::Vec2f& pos,
|
||||
const osg::Vec2f& delta );
|
||||
virtual ~EventVisitor();
|
||||
virtual bool traverse(Element& el);
|
||||
virtual bool apply(Element& el);
|
||||
|
||||
bool propagateEvent(const EventPtr& event);
|
||||
|
||||
protected:
|
||||
struct EventTarget
|
||||
{
|
||||
Element* element;
|
||||
osg::Vec2f local_pos,
|
||||
local_delta;
|
||||
};
|
||||
typedef std::deque<EventTarget> EventTargets;
|
||||
|
||||
EventTargets _target_path;
|
||||
TraverseMode _traverse_mode;
|
||||
};
|
||||
|
||||
} // namespace canvas
|
||||
} // namespace simgear
|
||||
|
||||
|
||||
#endif /* CANVAS_EVENTVISITOR_HXX_ */
|
||||
@@ -48,6 +48,15 @@ namespace canvas
|
||||
* cleaned up by the garbage collector.
|
||||
*/
|
||||
virtual void gcRelease(int key) = 0;
|
||||
|
||||
/**
|
||||
* Call a Nasal function with the given environment and arguments.
|
||||
*/
|
||||
virtual naRef callMethod( naRef code,
|
||||
naRef self,
|
||||
int argc,
|
||||
naRef* args,
|
||||
naRef locals ) = 0;
|
||||
};
|
||||
|
||||
} // namespace canvas
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#ifndef CANVAS_MOUSE_EVENT_HXX_
|
||||
#define CANVAS_MOUSE_EVENT_HXX_
|
||||
|
||||
#include "CanvasEvent.hxx"
|
||||
#include <osgGA/GUIEventAdapter>
|
||||
|
||||
namespace simgear
|
||||
@@ -26,32 +27,24 @@ namespace simgear
|
||||
namespace canvas
|
||||
{
|
||||
|
||||
class MouseEvent
|
||||
struct MouseEvent:
|
||||
public Event
|
||||
{
|
||||
public:
|
||||
typedef osgGA::GUIEventAdapter::EventType EventType;
|
||||
typedef osgGA::GUIEventAdapter::ScrollingMotion Scroll;
|
||||
MouseEvent():
|
||||
button(-1),
|
||||
state(-1),
|
||||
mod(-1)
|
||||
{}
|
||||
|
||||
MouseEvent(EventType type):
|
||||
type(type),
|
||||
x(-1), y(-1),
|
||||
dx(0), dy(0),
|
||||
button(-1),
|
||||
state(-1),
|
||||
mod(-1),
|
||||
scroll(osgGA::GUIEventAdapter::SCROLL_NONE)
|
||||
{}
|
||||
osg::Vec2f getPos() const { return pos; }
|
||||
osg::Vec3f getPos3() const { return osg::Vec3f(pos, 0); }
|
||||
osg::Vec2f getDelta() const { return delta; }
|
||||
|
||||
osg::Vec2f getPos() const { return osg::Vec2f(x, y); }
|
||||
osg::Vec3f getPos3() const { return osg::Vec3f(x, y, 0); }
|
||||
|
||||
EventType type;
|
||||
float x, y,
|
||||
dx, dy;
|
||||
int button, //<! Button for this event
|
||||
state, //<! Current button state
|
||||
mod; //<! Keyboard modifier state
|
||||
Scroll scroll;
|
||||
osg::Vec2f pos,
|
||||
delta;
|
||||
int button, //<! Button for this event
|
||||
state, //<! Current button state
|
||||
mod; //<! Keyboard modifier state
|
||||
};
|
||||
|
||||
} // namespace canvas
|
||||
|
||||
@@ -50,15 +50,21 @@ namespace canvas
|
||||
SG_FWD_DECL(Path)
|
||||
SG_FWD_DECL(Text)
|
||||
|
||||
SG_FWD_DECL(Event)
|
||||
SG_FWD_DECL(EventListener)
|
||||
SG_FWD_DECL(MouseEvent)
|
||||
SG_FWD_DECL(Placement)
|
||||
SG_FWD_DECL(SystemAdapter)
|
||||
|
||||
#undef SG_FWD_DECL
|
||||
|
||||
class EventVisitor;
|
||||
|
||||
typedef std::map<std::string, const SGPropertyNode*> Style;
|
||||
typedef ElementPtr (*ElementFactory)( const CanvasWeakPtr&,
|
||||
const SGPropertyNode_ptr&,
|
||||
const Style& );
|
||||
const Style&,
|
||||
Element* );
|
||||
|
||||
typedef osg::ref_ptr<osgText::Font> FontPtr;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
#include "CanvasElement.hxx"
|
||||
#include <simgear/canvas/CanvasEventVisitor.hxx>
|
||||
#include <simgear/canvas/MouseEvent.hxx>
|
||||
|
||||
#include <osg/Drawable>
|
||||
@@ -108,6 +109,13 @@ namespace canvas
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
naRef Element::addEventListener(const nasal::CallContext& ctx)
|
||||
{
|
||||
std::cout << "addEventListener " << _node->getPath() << std::endl;
|
||||
return naNil();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
SGConstPropertyNode_ptr Element::getProps() const
|
||||
{
|
||||
@@ -121,28 +129,41 @@ namespace canvas
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Element::handleMouseEvent(const MouseEvent& event)
|
||||
bool Element::accept(EventVisitor& visitor)
|
||||
{
|
||||
// Transform event to local coordinates
|
||||
const osg::Matrixd& m = _transform->getInverseMatrix();
|
||||
MouseEvent local_event = event;
|
||||
local_event.x = m(0, 0) * event.x + m(1, 0) * event.y + m(3, 0);
|
||||
local_event.y = m(0, 1) * event.x + m(1, 1) * event.y + m(3, 1);
|
||||
return visitor.apply(*this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Element::ascend(EventVisitor& visitor)
|
||||
{
|
||||
if( _parent )
|
||||
return _parent->accept(visitor);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Element::traverse(EventVisitor& visitor)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Element::hitBound(const osg::Vec2f& pos) const
|
||||
{
|
||||
const osg::Vec3f pos3(pos, 0);
|
||||
|
||||
// Drawables have a bounding box...
|
||||
if( _drawable )
|
||||
{
|
||||
if( !_drawable->getBound().contains(local_event.getPos3()) )
|
||||
if( !_drawable->getBound().contains(pos3) )
|
||||
return false;
|
||||
}
|
||||
// ... for other elements, i.e. groups only a bounding sphere is available
|
||||
else if( !_transform->getBound().contains(local_event.getPos3()) )
|
||||
else if( !_transform->getBound().contains(pos3) )
|
||||
return false;
|
||||
|
||||
local_event.dx = m(0, 0) * event.dx + m(1, 0) * event.dy;
|
||||
local_event.dy = m(0, 1) * event.dx + m(1, 1) * event.dy;
|
||||
|
||||
return handleLocalMouseEvent(local_event);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -253,8 +274,10 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
Element::Element( const CanvasWeakPtr& canvas,
|
||||
const SGPropertyNode_ptr& node,
|
||||
const Style& parent_style ):
|
||||
const Style& parent_style,
|
||||
Element* parent ):
|
||||
_canvas( canvas ),
|
||||
_parent( parent ),
|
||||
_transform_dirty( false ),
|
||||
_transform( new osg::MatrixTransform ),
|
||||
_node( node ),
|
||||
@@ -273,13 +296,11 @@ namespace canvas
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Element::handleLocalMouseEvent(const MouseEvent& event)
|
||||
void Element::callListeners(canvas::Event& event)
|
||||
{
|
||||
// std::cout << _node->getPath()
|
||||
// << " local: pos=(" << event.x << "|" << event.y << ") "
|
||||
// << "d=(" << event.dx << "|" << event.dx << ")"
|
||||
// << std::endl;
|
||||
return true;
|
||||
ListenerMap::iterator listeners = _listener.find(event.getType());
|
||||
if( listeners == _listener.end() )
|
||||
return;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -20,8 +20,11 @@
|
||||
#define CANVAS_ELEMENT_HXX_
|
||||
|
||||
#include <simgear/canvas/canvas_fwd.hxx>
|
||||
#include <simgear/canvas/CanvasEvent.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/misc/stdint.hxx> // for uint32_t
|
||||
#include <simgear/nasal/cppbind/Ghost.hxx>
|
||||
|
||||
#include <osg/BoundingBox>
|
||||
#include <osg/MatrixTransform>
|
||||
|
||||
@@ -38,7 +41,6 @@ namespace simgear
|
||||
namespace canvas
|
||||
{
|
||||
|
||||
class MouseEvent;
|
||||
class Element:
|
||||
public SGPropertyChangeListener
|
||||
{
|
||||
@@ -67,14 +69,17 @@ namespace canvas
|
||||
*/
|
||||
virtual void update(double dt);
|
||||
|
||||
naRef addEventListener(const nasal::CallContext& ctx);
|
||||
|
||||
SGConstPropertyNode_ptr getProps() const;
|
||||
SGPropertyNode_ptr getProps();
|
||||
|
||||
/**
|
||||
* Handle mouse event (transforms coordinates to local coordinate frame
|
||||
* and forwards event to #handleLocalMouseEvent)
|
||||
*/
|
||||
virtual bool handleMouseEvent(const canvas::MouseEvent& event);
|
||||
virtual bool accept(EventVisitor& visitor);
|
||||
virtual bool ascend(EventVisitor& visitor);
|
||||
virtual bool traverse(EventVisitor& visitor);
|
||||
|
||||
virtual bool hitBound(const osg::Vec2f& pos) const;
|
||||
|
||||
|
||||
osg::ref_ptr<osg::MatrixTransform> getMatrixTransform();
|
||||
|
||||
@@ -106,6 +111,7 @@ namespace canvas
|
||||
};
|
||||
|
||||
CanvasWeakPtr _canvas;
|
||||
Element *_parent;
|
||||
uint32_t _attributes_dirty;
|
||||
|
||||
bool _transform_dirty;
|
||||
@@ -117,9 +123,15 @@ namespace canvas
|
||||
StyleSetters _style_setters;
|
||||
std::vector<SGPropertyNode_ptr> _bounding_box;
|
||||
|
||||
typedef std::vector<EventListenerPtr> Listener;
|
||||
typedef std::map<Event::Type, Listener> ListenerMap;
|
||||
|
||||
ListenerMap _listener;
|
||||
|
||||
Element( const CanvasWeakPtr& canvas,
|
||||
const SGPropertyNode_ptr& node,
|
||||
const Style& parent_style );
|
||||
const Style& parent_style,
|
||||
Element* parent );
|
||||
|
||||
template<typename T, class C1, class C2>
|
||||
Element::StyleSetter
|
||||
@@ -156,7 +168,7 @@ namespace canvas
|
||||
return boost::bind(setter, instance, boost::bind(&getValue<T1>, _1));
|
||||
}
|
||||
|
||||
virtual bool handleLocalMouseEvent(const canvas::MouseEvent& event);
|
||||
void callListeners(canvas::Event& event);
|
||||
|
||||
virtual void childAdded(SGPropertyNode * child) {}
|
||||
virtual void childRemoved(SGPropertyNode * child){}
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "CanvasMap.hxx"
|
||||
#include "CanvasPath.hxx"
|
||||
#include "CanvasText.hxx"
|
||||
#include <simgear/canvas/CanvasEventVisitor.hxx>
|
||||
#include <simgear/canvas/MouseEvent.hxx>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
@@ -36,16 +38,18 @@ namespace canvas
|
||||
template<typename T>
|
||||
ElementPtr createElement( const CanvasWeakPtr& canvas,
|
||||
const SGPropertyNode_ptr& node,
|
||||
const Style& style )
|
||||
const Style& style,
|
||||
Element* parent )
|
||||
{
|
||||
return ElementPtr( new T(canvas, node, style) );
|
||||
return ElementPtr( new T(canvas, node, style, parent) );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Group::Group( const CanvasWeakPtr& canvas,
|
||||
const SGPropertyNode_ptr& node,
|
||||
const Style& parent_style ):
|
||||
Element(canvas, node, parent_style)
|
||||
const Style& parent_style,
|
||||
Element* parent ):
|
||||
Element(canvas, node, parent_style, parent)
|
||||
{
|
||||
_child_factories["group"] = &createElement<Group>;
|
||||
_child_factories["image"] = &createElement<Image>;
|
||||
@@ -91,12 +95,12 @@ namespace canvas
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Group::handleLocalMouseEvent(const canvas::MouseEvent& event)
|
||||
bool Group::traverse(EventVisitor& visitor)
|
||||
{
|
||||
// Iterate in reverse order as last child is displayed on top
|
||||
BOOST_REVERSE_FOREACH( ChildList::value_type child, _children )
|
||||
{
|
||||
if( child.second->handleMouseEvent(event) )
|
||||
if( child.second->accept(visitor) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -112,7 +116,7 @@ namespace canvas
|
||||
_child_factories.find( child->getNameString() );
|
||||
if( child_factory != _child_factories.end() )
|
||||
{
|
||||
ElementPtr element = child_factory->second(_canvas, child, _style);
|
||||
ElementPtr element = child_factory->second(_canvas, child, _style, this);
|
||||
|
||||
// Add to osg scene graph...
|
||||
_transform->addChild( element->getMatrixTransform() );
|
||||
|
||||
@@ -39,7 +39,8 @@ namespace canvas
|
||||
|
||||
Group( const CanvasWeakPtr& canvas,
|
||||
const SGPropertyNode_ptr& node,
|
||||
const Style& parent_style = Style() );
|
||||
const Style& parent_style = Style(),
|
||||
Element* parent = 0 );
|
||||
virtual ~Group();
|
||||
|
||||
ElementPtr createChild( const std::string& type,
|
||||
@@ -48,6 +49,8 @@ namespace canvas
|
||||
|
||||
virtual void update(double dt);
|
||||
|
||||
virtual bool traverse(EventVisitor& visitor);
|
||||
|
||||
protected:
|
||||
|
||||
typedef std::map<std::string, ElementFactory> ChildFactories;
|
||||
@@ -55,8 +58,6 @@ namespace canvas
|
||||
ChildFactories _child_factories;
|
||||
ChildList _children;
|
||||
|
||||
virtual bool handleLocalMouseEvent(const canvas::MouseEvent& event);
|
||||
|
||||
virtual void childAdded(SGPropertyNode * child);
|
||||
virtual void childRemoved(SGPropertyNode * child);
|
||||
virtual void childChanged(SGPropertyNode * child);
|
||||
|
||||
@@ -74,8 +74,9 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
Image::Image( const CanvasWeakPtr& canvas,
|
||||
const SGPropertyNode_ptr& node,
|
||||
const Style& parent_style ):
|
||||
Element(canvas, node, parent_style),
|
||||
const Style& parent_style,
|
||||
Element* parent ):
|
||||
Element(canvas, node, parent_style, parent),
|
||||
_texture(new osg::Texture2D),
|
||||
_node_src_rect( node->getNode("source", 0, true) )
|
||||
{
|
||||
|
||||
@@ -43,7 +43,8 @@ namespace canvas
|
||||
*/
|
||||
Image( const CanvasWeakPtr& canvas,
|
||||
const SGPropertyNode_ptr& node,
|
||||
const Style& parent_style );
|
||||
const Style& parent_style,
|
||||
Element* parent = 0 );
|
||||
virtual ~Image();
|
||||
|
||||
virtual void update(double dt);
|
||||
|
||||
@@ -47,8 +47,9 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
Map::Map( const CanvasWeakPtr& canvas,
|
||||
const SGPropertyNode_ptr& node,
|
||||
const Style& parent_style ):
|
||||
Group(canvas, node, parent_style),
|
||||
const Style& parent_style,
|
||||
Element* parent ):
|
||||
Group(canvas, node, parent_style, parent),
|
||||
// TODO make projection configurable
|
||||
_projection(new SansonFlamsteedProjection),
|
||||
_projection_dirty(true)
|
||||
|
||||
@@ -37,7 +37,8 @@ namespace canvas
|
||||
public:
|
||||
Map( const CanvasWeakPtr& canvas,
|
||||
const SGPropertyNode_ptr& node,
|
||||
const Style& parent_style );
|
||||
const Style& parent_style,
|
||||
Element* parent = 0 );
|
||||
virtual ~Map();
|
||||
|
||||
virtual void update(double dt);
|
||||
|
||||
@@ -355,8 +355,9 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
Path::Path( const CanvasWeakPtr& canvas,
|
||||
const SGPropertyNode_ptr& node,
|
||||
const Style& parent_style ):
|
||||
Element(canvas, node, parent_style),
|
||||
const Style& parent_style,
|
||||
Element* parent ):
|
||||
Element(canvas, node, parent_style, parent),
|
||||
_path( new PathDrawable(this) )
|
||||
{
|
||||
setDrawable(_path);
|
||||
|
||||
@@ -31,7 +31,8 @@ namespace canvas
|
||||
public:
|
||||
Path( const CanvasWeakPtr& canvas,
|
||||
const SGPropertyNode_ptr& node,
|
||||
const Style& parent_style );
|
||||
const Style& parent_style,
|
||||
Element* parent = 0 );
|
||||
virtual ~Path();
|
||||
|
||||
virtual void update(double dt);
|
||||
|
||||
@@ -177,8 +177,9 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
Text::Text( const CanvasWeakPtr& canvas,
|
||||
const SGPropertyNode_ptr& node,
|
||||
const Style& parent_style ):
|
||||
Element(canvas, node, parent_style),
|
||||
const Style& parent_style,
|
||||
Element* parent ):
|
||||
Element(canvas, node, parent_style, parent),
|
||||
_text( new Text::TextOSG(this) )
|
||||
{
|
||||
setDrawable(_text);
|
||||
|
||||
@@ -35,7 +35,8 @@ namespace canvas
|
||||
public:
|
||||
Text( const CanvasWeakPtr& canvas,
|
||||
const SGPropertyNode_ptr& node,
|
||||
const Style& parent_style );
|
||||
const Style& parent_style,
|
||||
Element* parent = 0 );
|
||||
~Text();
|
||||
|
||||
void setText(const char* text);
|
||||
|
||||
Reference in New Issue
Block a user