#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/KeyboardEvent.hxx>
+#include <simgear/canvas/events/MouseEvent.hxx>
#include <simgear/scene/util/parse_color.hxx>
#include <simgear/scene/util/RenderConstants.hxx>
void Canvas::CullCallback::operator()( osg::Node* node,
osg::NodeVisitor* nv )
{
- if( (nv->getTraversalMask() & simgear::MODEL_BIT) && !_canvas.expired() )
- _canvas.lock()->enableRendering();
+ if( (nv->getTraversalMask() & simgear::MODEL_BIT) )
+ {
+ CanvasPtr canvas = _canvas.lock();
+ if( canvas )
+ canvas->enableRendering();
+ }
traverse(node, nv);
}
{
_status = 0;
setStatusFlags(MISSING_SIZE_X | MISSING_SIZE_Y);
+
+ _root_group.reset( new Group(this, _node) );
+
+ // Remove automatically created property listener as we forward them on our
+ // own
+ _root_group->removeListener();
+ _cull_callback = new CullCallback(this);
}
//----------------------------------------------------------------------------
return _root_group;
}
+ //----------------------------------------------------------------------------
+ void Canvas::setLayout(const LayoutRef& layout)
+ {
+ _layout = layout;
+ _layout->setCanvas(this);
+ }
+
+ //----------------------------------------------------------------------------
+ void Canvas::setFocusElement(const ElementPtr& el)
+ {
+ if( el && el->getCanvas().lock() != this )
+ {
+ SG_LOG(SG_GUI, SG_WARN, "setFocusElement: element not from this canvas");
+ return;
+ }
+
+ // TODO focus out/in events
+ _focus_element = el;
+ }
+
+ //----------------------------------------------------------------------------
+ void Canvas::clearFocusElement()
+ {
+ _focus_element.reset();
+ }
+
//----------------------------------------------------------------------------
void Canvas::enableRendering(bool force)
{
//----------------------------------------------------------------------------
void Canvas::update(double delta_time_sec)
{
- if( (!_texture.serviceable() && _status != STATUS_DIRTY)
- || (_status & CREATE_FAILED) )
+ if( _status & (CREATE_FAILED | MISSING_SIZE) )
return;
- if( _status == STATUS_DIRTY )
+ if( _status & STATUS_DIRTY )
{
_texture.setSize(_size_x, _size_y);
}
}
+ if( _layout )
+ _layout->setGeometry(SGRecti(0, 0, _view_width, _view_height));
+
if( _visible || _render_always )
{
- BOOST_FOREACH(CanvasWeakPtr canvas, _child_canvases)
+ BOOST_FOREACH(CanvasWeakPtr canvas_weak, _child_canvases)
{
// TODO should we check if the image the child canvas is displayed
// within is really visible?
- if( !canvas.expired() )
- canvas.lock()->_visible = true;
+ CanvasPtr canvas = canvas_weak.lock();
+ if( canvas )
+ canvas->_visible = true;
}
if( _render_dirty )
{
// Also mark all canvases this canvas is displayed within as dirty
- BOOST_FOREACH(CanvasWeakPtr canvas, _parent_canvases)
+ BOOST_FOREACH(CanvasWeakPtr canvas_weak, _parent_canvases)
{
- if( !canvas.expired() )
- canvas.lock()->_render_dirty = true;
+ CanvasPtr canvas = canvas_weak.lock();
+ if( canvas )
+ canvas->_render_dirty = true;
}
}
if( placement_factory != _placement_factories.end() )
{
Placements& placements = _placements[ node->getIndex() ] =
- placement_factory->second
- (
- node,
- boost::static_pointer_cast<Canvas>(_self.lock())
- );
+ placement_factory->second(node, this);
node->setStringValue
(
"status-msg",
const EventListener& cb )
{
if( !_root_group.get() )
- throw std::runtime_error("Canvas::AddEventListener: no root group!");
+ throw std::runtime_error("Canvas::addEventListener: no root group!");
return _root_group->addEventListener(type, cb);
}
+ //----------------------------------------------------------------------------
+ bool Canvas::dispatchEvent(const EventPtr& event)
+ {
+ if( !_root_group.get() )
+ throw std::runtime_error("Canvas::dispatchEvent: no root group!");
+
+ return _root_group->dispatchEvent(event);
+ }
+
//----------------------------------------------------------------------------
void Canvas::setSizeX(int sx)
{
//----------------------------------------------------------------------------
bool Canvas::handleMouseEvent(const MouseEventPtr& event)
{
- if( !_root_group.get() )
+ if( !_root_group )
return false;
EventVisitor visitor( EventVisitor::TRAVERSE_DOWN,
return _event_manager->handleEvent(event, visitor.getPropagationPath());
}
+ //----------------------------------------------------------------------------
+ bool Canvas::handleKeyboardEvent(const KeyboardEventPtr& event)
+ {
+ ElementPtr target = _focus_element.lock();
+ if( !target )
+ target = _root_group;
+ if( !target )
+ return false;
+
+ return target->dispatchEvent(event);
+ }
+
+ //----------------------------------------------------------------------------
+ bool Canvas::propagateEvent( EventPtr const& event,
+ EventPropagationPath const& path )
+ {
+ return _event_manager->propagateEvent(event, path);
+ }
+
//----------------------------------------------------------------------------
void Canvas::childAdded( SGPropertyNode * parent,
SGPropertyNode * child )
//----------------------------------------------------------------------------
void Canvas::valueChanged(SGPropertyNode* node)
{
- if( boost::starts_with(node->getNameString(), "status")
- || node->getParent()->getNameString() == "bounding-box" )
+ const std::string& name = node->getNameString();
+
+ if( boost::starts_with(name, "status")
+ || boost::starts_with(name, "data-") )
return;
_render_dirty = true;
}
else if( node->getParent() == _node )
{
- if( node->getNameString() == "background" )
+ if( name == "background" )
{
osg::Vec4 color;
if( _texture.getCamera() && parseColor(node->getStringValue(), color) )
_render_dirty = true;
}
}
- else if( node->getNameString() == "mipmapping"
- || node->getNameString() == "coverage-samples"
- || node->getNameString() == "color-samples" )
+ else if( name == "mipmapping"
+ || name == "coverage-samples"
+ || name == "color-samples" )
{
_sampling_dirty = true;
}
- else if( node->getNameString() == "additive-blend" )
+ else if( name == "additive-blend" )
{
_texture.useAdditiveBlend( node->getBoolValue() );
}
- else if( node->getNameString() == "render-always" )
+ else if( name == "render-always" )
{
_render_always = node->getBoolValue();
}
- else if( node->getNameString() == "size" )
+ else if( name == "size" )
{
if( node->getIndex() == 0 )
setSizeX( node->getIntValue() );
else if( node->getIndex() == 1 )
setSizeY( node->getIntValue() );
}
- else if( node->getNameString() == "view" )
+ else if( name == "update" )
+ {
+ if( _root_group )
+ _root_group->update(0);
+ return update(0);
+ }
+ else if( name == "view" )
{
if( node->getIndex() == 0 )
setViewWidth( node->getIntValue() );
else if( node->getIndex() == 1 )
setViewHeight( node->getIntValue() );
}
- else if( node->getNameString() == "freeze" )
+ else if( name == "freeze" )
_texture.setRender( node->getBoolValue() );
else
handled = false;
return _system_adapter;
}
- //----------------------------------------------------------------------------
- void Canvas::setSelf(const PropertyBasedElementPtr& self)
- {
- PropertyBasedElement::setSelf(self);
-
- CanvasPtr canvas = boost::static_pointer_cast<Canvas>(self);
-
- _root_group.reset( new Group(canvas, _node) );
- _root_group->setSelf(_root_group);
-
- // Remove automatically created property listener as we forward them on our
- // own
- _root_group->removeListener();
-
- _cull_callback = new CullCallback(canvas);
- }
-
//----------------------------------------------------------------------------
void Canvas::setStatusFlags(unsigned int flags, bool set)
{
_status_msg = "Missing size-y";
else if( _status & CREATE_FAILED )
_status_msg = "Creating render target failed";
- else if( _status == STATUS_DIRTY )
+ else if( _status & STATUS_DIRTY )
_status_msg = "Creation pending...";
else
_status_msg = "Ok";