Implement Canvas single/double/tripple click handling.
- Implement click event creation like specified in
DOM Level 3:
* Check for max move distance between mousedown/up
and clicks
* Check for click timeout
* Count clicks and report double clicks
This commit is contained in:
@@ -5,6 +5,7 @@ set(HEADERS
|
|||||||
Canvas.hxx
|
Canvas.hxx
|
||||||
CanvasEvent.hxx
|
CanvasEvent.hxx
|
||||||
CanvasEventListener.hxx
|
CanvasEventListener.hxx
|
||||||
|
CanvasEventManager.hxx
|
||||||
CanvasEventTypes.hxx
|
CanvasEventTypes.hxx
|
||||||
CanvasEventVisitor.hxx
|
CanvasEventVisitor.hxx
|
||||||
CanvasMgr.hxx
|
CanvasMgr.hxx
|
||||||
@@ -19,6 +20,7 @@ set(SOURCES
|
|||||||
Canvas.cxx
|
Canvas.cxx
|
||||||
CanvasEvent.cxx
|
CanvasEvent.cxx
|
||||||
CanvasEventListener.cxx
|
CanvasEventListener.cxx
|
||||||
|
CanvasEventManager.cxx
|
||||||
CanvasEventVisitor.cxx
|
CanvasEventVisitor.cxx
|
||||||
CanvasMgr.cxx
|
CanvasMgr.cxx
|
||||||
CanvasPlacement.cxx
|
CanvasPlacement.cxx
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
#include "Canvas.hxx"
|
#include "Canvas.hxx"
|
||||||
|
#include "CanvasEventManager.hxx"
|
||||||
#include "CanvasEventVisitor.hxx"
|
#include "CanvasEventVisitor.hxx"
|
||||||
#include <simgear/canvas/MouseEvent.hxx>
|
#include <simgear/canvas/MouseEvent.hxx>
|
||||||
#include <simgear/canvas/CanvasPlacement.hxx>
|
#include <simgear/canvas/CanvasPlacement.hxx>
|
||||||
@@ -58,6 +59,7 @@ namespace canvas
|
|||||||
Canvas::Canvas(SGPropertyNode* node):
|
Canvas::Canvas(SGPropertyNode* node):
|
||||||
PropertyBasedElement(node),
|
PropertyBasedElement(node),
|
||||||
_canvas_mgr(0),
|
_canvas_mgr(0),
|
||||||
|
_event_manager(new EventManager),
|
||||||
_size_x(-1),
|
_size_x(-1),
|
||||||
_size_y(-1),
|
_size_y(-1),
|
||||||
_view_width(-1),
|
_view_width(-1),
|
||||||
@@ -356,9 +358,7 @@ namespace canvas
|
|||||||
if( !_root_group->accept(visitor) )
|
if( !_root_group->accept(visitor) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// TODO create special events like click/dblclick etc.
|
return _event_manager->handleEvent(event, visitor.getPropagationPath());
|
||||||
|
|
||||||
return visitor.propagateEvent(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -507,6 +507,7 @@ namespace canvas
|
|||||||
CanvasPtr canvas = boost::static_pointer_cast<Canvas>(self);
|
CanvasPtr canvas = boost::static_pointer_cast<Canvas>(self);
|
||||||
|
|
||||||
_root_group.reset( new Group(canvas, _node) );
|
_root_group.reset( new Group(canvas, _node) );
|
||||||
|
_root_group->setSelf(_root_group);
|
||||||
|
|
||||||
// Remove automatically created property listener as we forward them on our
|
// Remove automatically created property listener as we forward them on our
|
||||||
// own
|
// own
|
||||||
|
|||||||
@@ -134,6 +134,8 @@ namespace canvas
|
|||||||
SystemAdapterPtr _system_adapter;
|
SystemAdapterPtr _system_adapter;
|
||||||
CanvasMgr *_canvas_mgr;
|
CanvasMgr *_canvas_mgr;
|
||||||
|
|
||||||
|
std::auto_ptr<EventManager> _event_manager;
|
||||||
|
|
||||||
int _size_x,
|
int _size_x,
|
||||||
_size_y,
|
_size_y,
|
||||||
_view_width,
|
_view_width,
|
||||||
@@ -155,7 +157,7 @@ namespace canvas
|
|||||||
_visible;
|
_visible;
|
||||||
|
|
||||||
ODGauge _texture;
|
ODGauge _texture;
|
||||||
std::auto_ptr<Group> _root_group;
|
GroupPtr _root_group;
|
||||||
|
|
||||||
CullCallbackPtr _cull_callback;
|
CullCallbackPtr _cull_callback;
|
||||||
bool _render_always; //<! Used to disable automatic lazy rendering (culling)
|
bool _render_always; //<! Used to disable automatic lazy rendering (culling)
|
||||||
|
|||||||
@@ -62,6 +62,12 @@ namespace canvas
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
double Event::getTime() const
|
||||||
|
{
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Event::stopPropagation()
|
void Event::stopPropagation()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ namespace canvas
|
|||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
ElementWeakPtr target;
|
ElementWeakPtr target;
|
||||||
|
double time;
|
||||||
bool propagation_stopped;
|
bool propagation_stopped;
|
||||||
|
|
||||||
Event();
|
Event();
|
||||||
@@ -54,6 +55,9 @@ namespace canvas
|
|||||||
std::string getTypeString() const;
|
std::string getTypeString() const;
|
||||||
|
|
||||||
ElementWeakPtr getTarget() const;
|
ElementWeakPtr getTarget() const;
|
||||||
|
|
||||||
|
double getTime() const;
|
||||||
|
|
||||||
void stopPropagation();
|
void stopPropagation();
|
||||||
|
|
||||||
static Type strToType(const std::string& str);
|
static Type strToType(const std::string& str);
|
||||||
|
|||||||
@@ -0,0 +1,187 @@
|
|||||||
|
// Manage event handling inside a Canvas similar to the DOM Level 3 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 "CanvasEventManager.hxx"
|
||||||
|
#include "MouseEvent.hxx"
|
||||||
|
#include <simgear/canvas/elements/CanvasElement.hxx>
|
||||||
|
|
||||||
|
namespace simgear
|
||||||
|
{
|
||||||
|
namespace canvas
|
||||||
|
{
|
||||||
|
|
||||||
|
const unsigned int drag_threshold = 8;
|
||||||
|
const double multi_click_timeout = 0.4;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
EventManager::EventManager():
|
||||||
|
_current_click_count(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool EventManager::handleEvent( const MouseEventPtr& event,
|
||||||
|
const EventPropagationPath& path )
|
||||||
|
{
|
||||||
|
propagateEvent(event, path);
|
||||||
|
switch( event->type )
|
||||||
|
{
|
||||||
|
case Event::MOUSE_DOWN:
|
||||||
|
_last_mouse_down = StampedPropagationPath(path, event->getTime());
|
||||||
|
break;
|
||||||
|
case Event::MOUSE_UP:
|
||||||
|
{
|
||||||
|
if( _last_mouse_down.path.empty() )
|
||||||
|
// Ignore mouse up without any previous mouse down
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( checkClickDistance(path, _last_mouse_down.path) )
|
||||||
|
handleClick(event, getCommonAncestor(_last_mouse_down.path, path));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void EventManager::handleClick( const MouseEventPtr& event,
|
||||||
|
const EventPropagationPath& path )
|
||||||
|
{
|
||||||
|
MouseEventPtr click(new MouseEvent(*event));
|
||||||
|
click->type = Event::CLICK;
|
||||||
|
|
||||||
|
if( event->getTime() > _last_click.time + multi_click_timeout )
|
||||||
|
_current_click_count = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Maximum current click count is 3
|
||||||
|
_current_click_count = (_current_click_count % 3) + 1;
|
||||||
|
|
||||||
|
if( _current_click_count > 1 )
|
||||||
|
{
|
||||||
|
// Reset current click count if moved too far
|
||||||
|
if( !checkClickDistance(path, _last_click.path) )
|
||||||
|
_current_click_count = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
click->click_count = _current_click_count;
|
||||||
|
|
||||||
|
MouseEventPtr dbl_click;
|
||||||
|
if( _current_click_count == 2 )
|
||||||
|
{
|
||||||
|
dbl_click.reset(new MouseEvent(*click));
|
||||||
|
dbl_click->type = Event::DBL_CLICK;
|
||||||
|
}
|
||||||
|
|
||||||
|
propagateEvent(click, path);
|
||||||
|
|
||||||
|
if( dbl_click )
|
||||||
|
propagateEvent(dbl_click, getCommonAncestor(_last_click.path, path));
|
||||||
|
|
||||||
|
_last_click = StampedPropagationPath(path, event->getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
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
|
||||||
|
|
||||||
|
// Capturing phase
|
||||||
|
// 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";
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( mouse_event )
|
||||||
|
{
|
||||||
|
// Position and delta are specified in local coordinate system of
|
||||||
|
// current element
|
||||||
|
mouse_event->pos = it->local_pos;
|
||||||
|
mouse_event->delta = it->local_delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
el->callListeners(event);
|
||||||
|
|
||||||
|
if( event->propagation_stopped )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
EventManager::checkClickDistance( const EventPropagationPath& path1,
|
||||||
|
const EventPropagationPath& path2 ) const
|
||||||
|
{
|
||||||
|
osg::Vec2 delta = path1.front().local_pos - path2.front().local_pos;
|
||||||
|
return delta.x() < drag_threshold
|
||||||
|
&& delta.y() < drag_threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
EventPropagationPath
|
||||||
|
EventManager::getCommonAncestor( const EventPropagationPath& path1,
|
||||||
|
const EventPropagationPath& path2 ) const
|
||||||
|
{
|
||||||
|
if( path1.back().element.lock() == path2.back().element.lock() )
|
||||||
|
return path2;
|
||||||
|
|
||||||
|
EventPropagationPath path;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < path1.size() && i < path2.size(); ++i )
|
||||||
|
{
|
||||||
|
if( path1[i].element.lock() != path2[i].element.lock() )
|
||||||
|
break;
|
||||||
|
|
||||||
|
path.push_back(path2[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace canvas
|
||||||
|
} // namespace simgear
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
// Manage event handling inside a Canvas similar to the DOM Level 3 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_MANAGER_HXX_
|
||||||
|
#define CANVAS_EVENT_MANAGER_HXX_
|
||||||
|
|
||||||
|
#include "canvas_fwd.hxx"
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
namespace simgear
|
||||||
|
{
|
||||||
|
namespace canvas
|
||||||
|
{
|
||||||
|
|
||||||
|
struct EventTarget
|
||||||
|
{
|
||||||
|
ElementWeakPtr element;
|
||||||
|
osg::Vec2f local_pos,
|
||||||
|
local_delta;
|
||||||
|
};
|
||||||
|
typedef std::deque<EventTarget> EventPropagationPath;
|
||||||
|
|
||||||
|
class EventManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EventManager();
|
||||||
|
|
||||||
|
bool handleEvent( const MouseEventPtr& event,
|
||||||
|
const EventPropagationPath& path );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct StampedPropagationPath
|
||||||
|
{
|
||||||
|
StampedPropagationPath():
|
||||||
|
time(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
StampedPropagationPath(const EventPropagationPath& path, double time):
|
||||||
|
path(path),
|
||||||
|
time(time)
|
||||||
|
{}
|
||||||
|
|
||||||
|
EventPropagationPath path;
|
||||||
|
double time;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO if we really need the paths modify to not copy around the paths
|
||||||
|
// that much.
|
||||||
|
StampedPropagationPath _last_mouse_down,
|
||||||
|
_last_click;
|
||||||
|
size_t _current_click_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Propagate click event and handle multi-click (eg. create dblclick)
|
||||||
|
*/
|
||||||
|
void handleClick( 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
|
||||||
|
* dblclick event respectively.
|
||||||
|
*/
|
||||||
|
bool checkClickDistance( const EventPropagationPath& path1,
|
||||||
|
const EventPropagationPath& path2 ) const;
|
||||||
|
EventPropagationPath
|
||||||
|
getCommonAncestor( const EventPropagationPath& path1,
|
||||||
|
const EventPropagationPath& path2 ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace canvas
|
||||||
|
} // namespace simgear
|
||||||
|
|
||||||
|
#endif /* CANVAS_EVENT_MANAGER_HXX_ */
|
||||||
@@ -35,7 +35,7 @@ namespace canvas
|
|||||||
{
|
{
|
||||||
if( mode == TRAVERSE_DOWN )
|
if( mode == TRAVERSE_DOWN )
|
||||||
{
|
{
|
||||||
EventTarget target = {0, pos, delta};
|
EventTarget target = {ElementWeakPtr(), pos, delta};
|
||||||
_target_path.push_back(target);
|
_target_path.push_back(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ namespace canvas
|
|||||||
m(0, 1) * delta[0] + m(1, 1) * delta[1]
|
m(0, 1) * delta[0] + m(1, 1) * delta[1]
|
||||||
);
|
);
|
||||||
|
|
||||||
EventTarget target = {&el, local_pos, local_delta};
|
EventTarget target = {el.getWeakPtr(), local_pos, local_delta};
|
||||||
_target_path.push_back(target);
|
_target_path.push_back(target);
|
||||||
|
|
||||||
if( el.traverse(*this) || _target_path.size() <= 2 )
|
if( el.traverse(*this) || _target_path.size() <= 2 )
|
||||||
@@ -97,36 +97,9 @@ namespace canvas
|
|||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool EventVisitor::propagateEvent(const EventPtr& event)
|
const EventPropagationPath& EventVisitor::getPropagationPath() const
|
||||||
{
|
{
|
||||||
// Event propagation similar to DOM Level 3 event flow:
|
return _target_path;
|
||||||
// http://www.w3.org/TR/DOM-Level-3-Events/#event-flow
|
|
||||||
|
|
||||||
// Capturing phase
|
|
||||||
// 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";
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Bubbling phase
|
|
||||||
for( EventTargets::reverse_iterator it = _target_path.rbegin();
|
|
||||||
it != _target_path.rend();
|
|
||||||
++it )
|
|
||||||
{
|
|
||||||
if( !it->element )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
it->element->callListeners(event);
|
|
||||||
|
|
||||||
if( event->propagation_stopped )
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace canvas
|
} // namespace canvas
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#define CANVAS_EVENT_VISITOR_HXX_
|
#define CANVAS_EVENT_VISITOR_HXX_
|
||||||
|
|
||||||
#include "canvas_fwd.hxx"
|
#include "canvas_fwd.hxx"
|
||||||
#include <deque>
|
#include "CanvasEventManager.hxx"
|
||||||
|
|
||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
@@ -45,19 +45,13 @@ namespace canvas
|
|||||||
virtual bool traverse(Element& el);
|
virtual bool traverse(Element& el);
|
||||||
virtual bool apply(Element& el);
|
virtual bool apply(Element& el);
|
||||||
|
|
||||||
bool propagateEvent(const EventPtr& event);
|
const EventPropagationPath& getPropagationPath() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct EventTarget
|
|
||||||
{
|
|
||||||
Element* element;
|
|
||||||
osg::Vec2f local_pos,
|
|
||||||
local_delta;
|
|
||||||
};
|
|
||||||
typedef std::deque<EventTarget> EventTargets;
|
|
||||||
|
|
||||||
EventTargets _target_path;
|
TraverseMode _traverse_mode;
|
||||||
TraverseMode _traverse_mode;
|
EventPropagationPath _target_path;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace canvas
|
} // namespace canvas
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ namespace canvas
|
|||||||
MouseEvent():
|
MouseEvent():
|
||||||
button(-1),
|
button(-1),
|
||||||
state(-1),
|
state(-1),
|
||||||
mod(-1)
|
mod(-1),
|
||||||
|
click_count(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
osg::Vec2f getPos() const { return pos; }
|
osg::Vec2f getPos() const { return pos; }
|
||||||
@@ -47,11 +48,14 @@ namespace canvas
|
|||||||
float getDeltaX() const { return delta.x(); }
|
float getDeltaX() const { return delta.x(); }
|
||||||
float getDeltaY() const { return delta.y(); }
|
float getDeltaY() const { return delta.y(); }
|
||||||
|
|
||||||
|
int getCurrentClickCount() const { return click_count; }
|
||||||
|
|
||||||
osg::Vec2f pos,
|
osg::Vec2f pos,
|
||||||
delta;
|
delta;
|
||||||
int button, //<! Button for this event
|
int button, //<! Button for this event
|
||||||
state, //<! Current button state
|
state, //<! Current button state
|
||||||
mod; //<! Keyboard modifier state
|
mod, //<! Keyboard modifier state
|
||||||
|
click_count; //<! Current click count
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace canvas
|
} // namespace canvas
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ namespace canvas
|
|||||||
|
|
||||||
#undef SG_FWD_DECL
|
#undef SG_FWD_DECL
|
||||||
|
|
||||||
|
class EventManager;
|
||||||
class EventVisitor;
|
class EventVisitor;
|
||||||
|
|
||||||
typedef std::map<std::string, const SGPropertyNode*> Style;
|
typedef std::map<std::string, const SGPropertyNode*> Style;
|
||||||
|
|||||||
@@ -54,6 +54,12 @@ namespace canvas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
ElementWeakPtr Element::getWeakPtr() const
|
||||||
|
{
|
||||||
|
return boost::static_pointer_cast<Element>(_self.lock());
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Element::update(double dt)
|
void Element::update(double dt)
|
||||||
{
|
{
|
||||||
@@ -140,18 +146,6 @@ namespace canvas
|
|||||||
return naNil();
|
return naNil();
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
SGConstPropertyNode_ptr Element::getProps() const
|
|
||||||
{
|
|
||||||
return _node;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
SGPropertyNode_ptr Element::getProps()
|
|
||||||
{
|
|
||||||
return _node;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool Element::accept(EventVisitor& visitor)
|
bool Element::accept(EventVisitor& visitor)
|
||||||
{
|
{
|
||||||
@@ -339,17 +333,14 @@ namespace canvas
|
|||||||
const SGPropertyNode_ptr& node,
|
const SGPropertyNode_ptr& node,
|
||||||
const Style& parent_style,
|
const Style& parent_style,
|
||||||
Element* parent ):
|
Element* parent ):
|
||||||
|
PropertyBasedElement(node),
|
||||||
_canvas( canvas ),
|
_canvas( canvas ),
|
||||||
_parent( parent ),
|
_parent( parent ),
|
||||||
_transform_dirty( false ),
|
_transform_dirty( false ),
|
||||||
_transform( new osg::MatrixTransform ),
|
_transform( new osg::MatrixTransform ),
|
||||||
_node( node ),
|
|
||||||
_style( parent_style ),
|
_style( parent_style ),
|
||||||
_drawable( 0 )
|
_drawable( 0 )
|
||||||
{
|
{
|
||||||
assert( _node );
|
|
||||||
_node->addChangeListener(this);
|
|
||||||
|
|
||||||
SG_LOG
|
SG_LOG
|
||||||
(
|
(
|
||||||
SG_GL,
|
SG_GL,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include <simgear/canvas/canvas_fwd.hxx>
|
#include <simgear/canvas/canvas_fwd.hxx>
|
||||||
#include <simgear/canvas/CanvasEvent.hxx>
|
#include <simgear/canvas/CanvasEvent.hxx>
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/PropertyBasedElement.hxx>
|
||||||
#include <simgear/misc/stdint.hxx> // for uint32_t
|
#include <simgear/misc/stdint.hxx> // for uint32_t
|
||||||
#include <simgear/nasal/cppbind/Ghost.hxx>
|
#include <simgear/nasal/cppbind/Ghost.hxx>
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ namespace canvas
|
|||||||
{
|
{
|
||||||
|
|
||||||
class Element:
|
class Element:
|
||||||
public SGPropertyChangeListener
|
public PropertyBasedElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef boost::function<void(const SGPropertyNode*)> StyleSetter;
|
typedef boost::function<void(const SGPropertyNode*)> StyleSetter;
|
||||||
@@ -62,6 +62,8 @@ namespace canvas
|
|||||||
*/
|
*/
|
||||||
virtual ~Element() = 0;
|
virtual ~Element() = 0;
|
||||||
|
|
||||||
|
ElementWeakPtr getWeakPtr() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called every frame to update internal state
|
* Called every frame to update internal state
|
||||||
*
|
*
|
||||||
@@ -71,9 +73,6 @@ namespace canvas
|
|||||||
|
|
||||||
naRef addEventListener(const nasal::CallContext& ctx);
|
naRef addEventListener(const nasal::CallContext& ctx);
|
||||||
|
|
||||||
SGConstPropertyNode_ptr getProps() const;
|
|
||||||
SGPropertyNode_ptr getProps();
|
|
||||||
|
|
||||||
virtual bool accept(EventVisitor& visitor);
|
virtual bool accept(EventVisitor& visitor);
|
||||||
virtual bool ascend(EventVisitor& visitor);
|
virtual bool ascend(EventVisitor& visitor);
|
||||||
virtual bool traverse(EventVisitor& visitor);
|
virtual bool traverse(EventVisitor& visitor);
|
||||||
@@ -121,13 +120,13 @@ namespace canvas
|
|||||||
|
|
||||||
CanvasWeakPtr _canvas;
|
CanvasWeakPtr _canvas;
|
||||||
Element *_parent;
|
Element *_parent;
|
||||||
|
|
||||||
uint32_t _attributes_dirty;
|
uint32_t _attributes_dirty;
|
||||||
|
|
||||||
bool _transform_dirty;
|
bool _transform_dirty;
|
||||||
osg::ref_ptr<osg::MatrixTransform> _transform;
|
osg::ref_ptr<osg::MatrixTransform> _transform;
|
||||||
std::vector<TransformType> _transform_types;
|
std::vector<TransformType> _transform_types;
|
||||||
|
|
||||||
SGPropertyNode_ptr _node;
|
|
||||||
Style _style;
|
Style _style;
|
||||||
StyleSetters _style_setters;
|
StyleSetters _style_setters;
|
||||||
std::vector<SGPropertyNode_ptr> _bounding_box;
|
std::vector<SGPropertyNode_ptr> _bounding_box;
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ namespace canvas
|
|||||||
const Style& style,
|
const Style& style,
|
||||||
Element* parent )
|
Element* parent )
|
||||||
{
|
{
|
||||||
return ElementPtr( new T(canvas, node, style, parent) );
|
ElementPtr el( new T(canvas, node, style, parent) );
|
||||||
|
el->setSelf(el);
|
||||||
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user