diff --git a/docs-mini/README.canvas b/docs-mini/README.canvas
index 670f1d17d..8cc0b3004 100644
--- a/docs-mini/README.canvas
+++ b/docs-mini/README.canvas
@@ -2,7 +2,7 @@ Canvas - A 2D Drawing API
 =========================
 
 Author: Thomas Geymayer <admin@tomprogs.at>
-Revision: 2012/05/04
+Revision: 2012/05/18
 
 Introduction
 ------------
@@ -22,11 +22,11 @@ Creating a canvas
 A new canvas can be instantiated by creating a node /canvas/texture[<INDEX>]
 with at least the following children:
 
- <size-x type="int">       The width of the underlying texture
- <size-y type="int">       The height of the underlying texture
+ <size n="0" type="int">       The width of the underlying texture
+ <size n="1" type="int">       The height of the underlying texture
 
- <view-width type="int">   The width of the canvas
- <view-height type="int">  The height of the canvas
+ <view n="0" type="int">    The width of the canvas
+ <view n="1" type="int">    The height of the canvas
 
 The dimensions of the canvas are needed to be able to use textures with
 different resolutions but use the same units for rendering to the canvas.
@@ -60,6 +60,7 @@ only drawing Text is possible:
     <red type="float">
     <green type="float">
     <blue type="float">
+    <alpha type="float">
   </NAME>
 
 * Text:
@@ -71,7 +72,9 @@ only drawing Text is possible:
                               2. aircraft-dir
                               3. $FG_DATA/Fonts
                               4. Default osg font paths
- <size type="float">         The font size (default: 32)
+ <character-size type="float">          The font size (default: 32)
+ <character-aspect-ratio type="float">  Ratio between character height and width
+                                        (default: 1)
  <tf>               A 3x3 transformation matrix specified by 6 values
                     (child elements <a>, ..., <f>) See
                     http://www.w3.org/TR/SVG/coords.html#TransformMatrixDefined
@@ -129,17 +132,24 @@ Example
 
 <canvas>
   <texture>
-    <size-x type="int">384</size-x>
-    <size-y type="int">512</size-y>
-    <view-width type="int">768</view-width>
-    <view-height type="int">1024</view-height>
+    <size n="0" type="int">384</size-x>
+    <size n="1" type="int">512</size-y>
+    <view n="0" type="int">768</view-width>
+    <view n="1" type="int">1024</view-height>
     <mipmapping type="bool">false</mipmapping>
     <coverage-samples type="int">0</coverage-samples>
     <color-samples type="int">0</color-samples>
+    <color-background>
+      <red type="float">0</red>
+      <green type="float">0.02</green>
+      <blue type="float">0</blue>
+      <alpha type="float">1</alpha>
+    </color-background>
     <group>
       <text>
         <text type="string">TEST MESSAGE</text>
         <font type="string">helvetica_bold.txf</font>
+        <character-size type="float">40</character-size>
         <tf>
           <!-- Translate (18|50) -->
           <tx>18</tx>
diff --git a/src/Canvas/CMakeLists.txt b/src/Canvas/CMakeLists.txt
index 1dde0d26b..5de9945c0 100644
--- a/src/Canvas/CMakeLists.txt
+++ b/src/Canvas/CMakeLists.txt
@@ -6,6 +6,7 @@ set(SOURCES
   elements/element.cxx
   elements/group.cxx
   elements/text.cxx
+  property_helper.cxx
 )
 
 set(HEADERS
@@ -14,6 +15,7 @@ set(HEADERS
   elements/element.hxx
   elements/group.hxx
   elements/text.hxx
+  property_helper.hxx
 )
     
 flightgear_component(Canvas "${SOURCES}" "${HEADERS}")
diff --git a/src/Canvas/canvas.cxx b/src/Canvas/canvas.cxx
index 31e82653a..e82c08123 100644
--- a/src/Canvas/canvas.cxx
+++ b/src/Canvas/canvas.cxx
@@ -18,6 +18,7 @@
 
 #include "canvas.hxx"
 #include "elements/group.hxx"
+#include <Canvas/property_helper.hxx>
 
 #include <osg/Camera>
 #include <osg/Geode>
@@ -25,9 +26,6 @@
 
 #include <iostream>
 
-//#include <Main/globals.hxx>
-//#include <Viewer/renderer.hxx>
-
 //------------------------------------------------------------------------------
 /**
  * Callback used to disable/enable rendering to the texture if it is not
@@ -97,8 +95,9 @@ Canvas::Canvas():
   _view_width(-1),
   _view_height(-1),
   _status(0),
-  _node(0),
-  _sampling_dirty(false)
+  _sampling_dirty(false),
+  _color_dirty(true),
+  _node(0)
 {
   setStatusFlags(MISSING_SIZE_X | MISSING_SIZE_Y);
 
@@ -110,7 +109,10 @@ Canvas::Canvas():
 //------------------------------------------------------------------------------
 Canvas::~Canvas()
 {
+  clearPlacements();
 
+  unbind();
+  _node = 0;
 }
 
 //------------------------------------------------------------------------------
@@ -122,23 +124,21 @@ int Canvas::getStatus() const
 //------------------------------------------------------------------------------
 void Canvas::reset(SGPropertyNode* node)
 {
-  if( _node )
-  {
-    _node->untie("size[0]");
-    _node->untie("size[1]");
-    _node->untie("view[0]");
-    _node->untie("view[1]");
-    _node->untie("status");
-    _node->untie("status-msg");
-    _node->removeChangeListener(this);
-    _node = 0;
-  }
+  if( node )
+    SG_LOG
+    (
+      SG_GL,
+      SG_INFO,
+      "Canvas::reset() texture[" << node->getIndex() << "]"
+    );
 
+  unbind();
+
+  _node = node;
   setStatusFlags(MISSING_SIZE_X | MISSING_SIZE_Y);
 
-  if( node )
+  if( _node )
   {
-    _node = node;
     _node->tie
     (
       "size[0]",
@@ -174,6 +174,14 @@ void Canvas::reset(SGPropertyNode* node)
       SGRawValueMethods<Canvas, const char*>(*this, &Canvas::getStatusMsg)
     );
     _node->addChangeListener(this);
+
+    canvas::linkColorNodes
+    (
+      "color-background",
+      _node,
+      _color_background,
+      osg::Vec4f(0,0,0,1)
+    );
   }
 }
 
@@ -217,6 +225,17 @@ void Canvas::update(double delta_time_sec)
     );
     _sampling_dirty = false;
   }
+  if( _color_dirty )
+  {
+    _texture.getCamera()->setClearColor
+    (
+      osg::Vec4( _color_background[0]->getFloatValue(),
+                 _color_background[1]->getFloatValue(),
+                 _color_background[2]->getFloatValue(),
+                 _color_background[3]->getFloatValue() )
+    );
+    _color_dirty = false;
+  }
 
   while( !_dirty_placements.empty() )
   {
@@ -345,8 +364,6 @@ void Canvas::childAdded( SGPropertyNode * parent,
   {
     _dirty_placements.push_back(child);
   }
-//  else
-//    std::cout << "Canvas::childAdded: " << child->getPath() << std::endl;
 }
 
 //------------------------------------------------------------------------------
@@ -358,24 +375,29 @@ void Canvas::childRemoved( SGPropertyNode * parent,
 
   if( child->getNameString() == "placement" )
     clearPlacements(child->getIndex());
-  else
-    std::cout << "Canvas::childRemoved: " << child->getPath() << std::endl;
 }
 
 //----------------------------------------------------------------------------
 void Canvas::valueChanged(SGPropertyNode * node)
 {
-  if( node->getParent()->getParent() == _node
-      && node->getParent()->getNameString() == "placement" )
+  if( node->getParent()->getParent() == _node )
   {
-    // prevent double updates...
-    for( size_t i = 0; i < _dirty_placements.size(); ++i )
+    if(    !_color_background.empty()
+        && _color_background[0]->getParent() == node->getParent() )
     {
-      if( node->getParent() == _dirty_placements[i] )
-        return;
+      _color_dirty = true;
     }
+    else if( node->getParent()->getNameString() == "placement" )
+    {
+      // prevent double updates...
+      for( size_t i = 0; i < _dirty_placements.size(); ++i )
+      {
+        if( node->getParent() == _dirty_placements[i] )
+          return;
+      }
 
-    _dirty_placements.push_back(node->getParent());
+      _dirty_placements.push_back(node->getParent());
+    }
   }
   else if( node->getParent() == _node )
   {
@@ -428,3 +450,26 @@ void Canvas::clearPlacements(int index)
     parent->removeChild(group);
   }
 }
+
+//------------------------------------------------------------------------------
+void Canvas::clearPlacements()
+{
+  for(size_t i = 0; i < _placements.size(); ++i)
+    clearPlacements(i);
+  _placements.clear();
+}
+
+//------------------------------------------------------------------------------
+void Canvas::unbind()
+{
+  if( !_node )
+    return;
+
+  _node->untie("size[0]");
+  _node->untie("size[1]");
+  _node->untie("view[0]");
+  _node->untie("view[1]");
+  _node->untie("status");
+  _node->untie("status-msg");
+  _node->removeChangeListener(this);
+}
diff --git a/src/Canvas/canvas.hxx b/src/Canvas/canvas.hxx
index 1769b8ed4..9094825d4 100644
--- a/src/Canvas/canvas.hxx
+++ b/src/Canvas/canvas.hxx
@@ -73,6 +73,9 @@ class Canvas:
 
   private:
 
+    Canvas(const Canvas&); // = delete;
+    Canvas& operator=(const Canvas&); // = delete;
+
     int _size_x,
         _size_y,
         _view_width,
@@ -81,10 +84,13 @@ class Canvas:
     int         _status;
     std::string _status_msg;
 
-    FGODGauge       _texture;
-    SGPropertyNode *_node;
+    bool _sampling_dirty,
+         _color_dirty;
 
-    bool _sampling_dirty;
+    FGODGauge _texture;
+
+    SGPropertyNode_ptr              _node;
+    std::vector<SGPropertyNode_ptr> _color_background;
 
     osg::ref_ptr<osg::NodeCallback> _camera_callback;
     osg::ref_ptr<osg::NodeCallback> _cull_callback;
@@ -96,6 +102,9 @@ class Canvas:
 
     void setStatusFlags(unsigned int flags, bool set = true);
     void clearPlacements(int index);
+    void clearPlacements();
+
+    void unbind();
 };
 
 #endif /* CANVAS_HXX_ */
diff --git a/src/Canvas/canvas_mgr.cxx b/src/Canvas/canvas_mgr.cxx
index eab30b581..72db55fd0 100644
--- a/src/Canvas/canvas_mgr.cxx
+++ b/src/Canvas/canvas_mgr.cxx
@@ -73,7 +73,8 @@ void CanvasMgr::unbind()
 void CanvasMgr::update(double delta_time_sec)
 {
  for( size_t i = 0; i < _canvases.size(); ++i )
-   _canvases[i].update(delta_time_sec);
+   if( _canvases[i] )
+     _canvases[i]->update(delta_time_sec);
 }
 
 //------------------------------------------------------------------------------
@@ -85,8 +86,6 @@ void CanvasMgr::childAdded( SGPropertyNode * parent,
 
   if( child->getNameString() == "texture" )
     textureAdded(child);
-  else
-    std::cout << "CanvasMgr::childAdded: " << child->getPath() << std::endl;
 }
 
 //------------------------------------------------------------------------------
@@ -96,7 +95,16 @@ void CanvasMgr::childRemoved( SGPropertyNode * parent,
   if( parent != _props )
     return;
 
-  std::cout << "CanvasMgr::childRemoved: " << child->getPath() << std::endl;
+  if( child->getNameString() == "texture" )
+  {
+    size_t index = child->getIndex();
+
+    if( index >= _canvases.size() )
+      SG_LOG(SG_GL, SG_WARN, "can't removed unknown texture[" << index << "]!");
+    else
+      // remove the canvas...
+      _canvases[index].reset();
+  }
 }
 
 //------------------------------------------------------------------------------
@@ -108,17 +116,16 @@ void CanvasMgr::textureAdded(SGPropertyNode* node)
   {
     if( index > _canvases.size() )
       SG_LOG(SG_GL, SG_WARN, "Skipping unused texture slot(s)!");
-    SG_LOG(SG_GL, SG_INFO, "Add new texture[" << index << "]");
 
     _canvases.resize(index + 1);
-    _canvases[index];
   }
   else
   {
     SG_LOG(SG_GL, SG_WARN, "texture[" << index << "] already exists!");
   }
 
-  _canvases[index].reset(node);
+  _canvases[index].reset( new Canvas() );
+  _canvases[index]->reset(node);
 }
 
 //------------------------------------------------------------------------------
@@ -132,13 +139,3 @@ void CanvasMgr::triggerChangeRecursive(SGPropertyNode* node)
   for( int i = 0; i < node->nChildren(); ++i )
     triggerChangeRecursive( node->getChild(i) );
 }
-
-//------------------------------------------------------------------------------
-template<class T>
-T CanvasMgr::getParam(const SGPropertyNode* node, const char* prop)
-{
-  const SGPropertyNode* child = node->getChild(prop);
-  if( !child )
-    throw std::runtime_error(std::string("Missing property ") + prop);
-  return getValue<T>(child);
-}
diff --git a/src/Canvas/canvas_mgr.hxx b/src/Canvas/canvas_mgr.hxx
index b3b5bac0e..893b50e88 100644
--- a/src/Canvas/canvas_mgr.hxx
+++ b/src/Canvas/canvas_mgr.hxx
@@ -26,6 +26,7 @@
 #include <vector>
 
 class Canvas;
+typedef boost::shared_ptr<Canvas> CanvasPtr;
 
 class CanvasMgr:
   public SGSubsystem,
@@ -55,7 +56,7 @@ class CanvasMgr:
     SGPropertyNode_ptr _props;
 
     /** The actual canvases */
-    std::vector<Canvas> _canvases;
+    std::vector<CanvasPtr> _canvases;
 
     void textureAdded(SGPropertyNode* node);
 
@@ -65,12 +66,6 @@ class CanvasMgr:
      */
     void triggerChangeRecursive(SGPropertyNode* node);
 
-    /**
-     * Get the value of a property or throw an exception if it doesn't exist.
-     */
-    template<class T>
-    T getParam(const SGPropertyNode* node, const char* prop);
-
 };
 
 #endif /* CANVAS_MGR_H_ */
diff --git a/src/Canvas/elements/element.cxx b/src/Canvas/elements/element.cxx
index 119f109e6..87ce8e609 100644
--- a/src/Canvas/elements/element.cxx
+++ b/src/Canvas/elements/element.cxx
@@ -17,10 +17,13 @@
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 #include "element.hxx"
-#include <cassert>
+#include <Canvas/property_helper.hxx>
 
 #include <osg/Drawable>
 
+#include <cassert>
+#include <cstring>
+
 namespace canvas
 {
   const std::string NAME_TRANSFORM = "tf";
@@ -33,12 +36,6 @@ namespace canvas
 
   }
 
-  //----------------------------------------------------------------------------
-  SGPropertyNode* Element::getPropertyNode()
-  {
-    return _node;
-  }
-
   //----------------------------------------------------------------------------
   void Element::update(double dt)
   {
@@ -97,7 +94,7 @@ namespace canvas
       colorChanged( osg::Vec4( _color[0]->getFloatValue(),
                                _color[1]->getFloatValue(),
                                _color[2]->getFloatValue(),
-                               1 ) );
+                               _color[3]->getFloatValue() ) );
       _attributes_dirty &= ~COLOR;
     }
 
@@ -106,18 +103,19 @@ namespace canvas
       colorFillChanged( osg::Vec4( _color_fill[0]->getFloatValue(),
                                    _color_fill[1]->getFloatValue(),
                                    _color_fill[2]->getFloatValue(),
-                                   1 ) );
+                                   _color_fill[3]->getFloatValue() ) );
       _attributes_dirty &= ~COLOR_FILL;
     }
 
-    if( _drawable && (_attributes_dirty & BOUNDING_BOX) )
+    if( !_bounding_box.empty() )
     {
-      _bounding_box[0]->setFloatValue(_drawable->getBound()._min.x());
-      _bounding_box[1]->setFloatValue(_drawable->getBound()._min.y());
-      _bounding_box[2]->setFloatValue(_drawable->getBound()._max.x());
-      _bounding_box[3]->setFloatValue(_drawable->getBound()._max.y());
+      assert( _drawable );
 
-      _attributes_dirty &= ~BOUNDING_BOX;
+      const osg::BoundingBox& bb = _drawable->getBound();
+      _bounding_box[0]->setFloatValue(bb._min.x());
+      _bounding_box[1]->setFloatValue(bb._min.y());
+      _bounding_box[2]->setFloatValue(bb._max.x());
+      _bounding_box[3]->setFloatValue(bb._max.y());
     }
   }
 
@@ -128,29 +126,22 @@ namespace canvas
   }
 
   //----------------------------------------------------------------------------
-  Element::Element(SGPropertyNode* node, uint32_t attributes_used):
-    _node( node ),
-    _drawable( 0 ),
+  Element::Element(SGPropertyNode_ptr node, uint32_t attributes_used):
     _attributes_used( attributes_used ),
-    _attributes_dirty( 0 ),
+    _attributes_dirty( attributes_used ),
     _transform_dirty( false ),
-    _transform( new osg::MatrixTransform )
+    _transform( new osg::MatrixTransform ),
+    _node( node ),
+    _drawable( 0 )
   {
     assert( _node );
     _node->addChangeListener(this);
 
     if( _attributes_used & COLOR )
-      linkColorNodes("color", _color, osg::Vec4f(0,1,0,1));
+      linkColorNodes("color", _node, _color, osg::Vec4f(0,1,0,1));
+
     if( _attributes_used & COLOR_FILL )
-      linkColorNodes("color-fill", _color_fill);
-    if( _attributes_used & BOUNDING_BOX )
-    {
-      SGPropertyNode* bb = _node->getChild("bounding-box", 0, true);
-      _bounding_box[0] = bb->getChild("x-min", 0, true);
-      _bounding_box[1] = bb->getChild("y-min", 0, true);
-      _bounding_box[2] = bb->getChild("x-max", 0, true);
-      _bounding_box[3] = bb->getChild("y-max", 0, true);
-    }
+      linkColorNodes("color-fill", _node, _color_fill);
 
     SG_LOG
     (
@@ -161,22 +152,19 @@ namespace canvas
   }
 
   //----------------------------------------------------------------------------
-  void Element::linkColorNodes( const char* name,
-                                SGPropertyNode** nodes,
-                                const osg::Vec4& def )
+  void Element::setDrawable( osg::Drawable* drawable )
   {
-    // Don't tie to allow the usage of aliases
-    SGPropertyNode* color = _node->getChild(name, 0, true);
+    _drawable = drawable;
+    assert( _drawable );
 
-    static const char* color_names[] = {"red", "green", "blue"};
-    for( size_t i = 0; i < sizeof(color_names)/sizeof(color_names[0]); ++i )
+    if( _attributes_used & BOUNDING_BOX )
     {
-      color->setFloatValue
-      (
-        color_names[i],
-        color->getFloatValue(color_names[i], def[i])
-      );
-      nodes[i] = color->getChild(color_names[i]);
+      SGPropertyNode* bb_node = _node->getChild("bounding-box", 0, true);
+      _bounding_box.resize(4);
+      _bounding_box[0] = bb_node->getChild("min-x", 0, true);
+      _bounding_box[1] = bb_node->getChild("min-y", 0, true);
+      _bounding_box[2] = bb_node->getChild("max-x", 0, true);
+      _bounding_box[3] = bb_node->getChild("max-y", 0, true);
     }
   }
 
@@ -254,13 +242,18 @@ namespace canvas
     {
       if( parent->getNameString() == NAME_TRANSFORM )
         _transform_dirty = true;
-      else if( parent->getNameString() == NAME_COLOR )
+      else if( !_color.empty() && _color[0]->getParent() == parent )
         _attributes_dirty |= COLOR;
-      else if( parent->getNameString() == NAME_COLOR_FILL )
+      else if( !_color_fill.empty() && _color_fill[0]->getParent() == parent )
         _attributes_dirty |= COLOR_FILL;
     }
-    else
-      childChanged(child);
+    else if( parent == _node )
+    {
+      if( child->getNameString() == "update" )
+        update(0);
+      else
+        childChanged(child);
+    }
   }
 
 } // namespace canvas
diff --git a/src/Canvas/elements/element.hxx b/src/Canvas/elements/element.hxx
index b17a02977..3c9730e66 100644
--- a/src/Canvas/elements/element.hxx
+++ b/src/Canvas/elements/element.hxx
@@ -36,7 +36,6 @@ namespace canvas
   {
     public:
       virtual ~Element() = 0;
-      SGPropertyNode* getPropertyNode();
 
       /**
        * Called every frame to update internal state
@@ -53,7 +52,8 @@ namespace canvas
       {
         COLOR           = 0x0001,
         COLOR_FILL      = 0x0002,
-        BOUNDING_BOX    = 0x0004
+        BOUNDING_BOX    = 0x0004,
+        LAST_ATTRIBUTE  = BOUNDING_BOX
       };
 
       enum TransformType
@@ -65,9 +65,6 @@ namespace canvas
         TT_SCALE
       };
 
-      SGPropertyNode *_node;
-      osg::Drawable  *_drawable;
-
       uint32_t _attributes_used;
       uint32_t _attributes_dirty;
 
@@ -75,11 +72,12 @@ namespace canvas
       osg::ref_ptr<osg::MatrixTransform>    _transform;
       std::vector<TransformType>            _transform_types;
 
-      SGPropertyNode    *_bounding_box[4]; ///<! x-min, y-min, x-max, y-max
-      SGPropertyNode    *_color[3];
-      SGPropertyNode    *_color_fill[3];
+      SGPropertyNode_ptr                _node;
+      std::vector<SGPropertyNode_ptr>   _color,
+                                        _color_fill;
+      std::vector<SGPropertyNode_ptr>   _bounding_box;
 
-      Element(SGPropertyNode* node, uint32_t attributes_used = 0);
+      Element(SGPropertyNode_ptr node, uint32_t attributes_used = 0);
 
       virtual void childAdded(SGPropertyNode * child)  {}
       virtual void childRemoved(SGPropertyNode * child){}
@@ -88,11 +86,12 @@ namespace canvas
       virtual void colorChanged(const osg::Vec4& color)  {}
       virtual void colorFillChanged(const osg::Vec4& color){}
 
-      void linkColorNodes( const char* name,
-                           SGPropertyNode** nodes,
-                           const osg::Vec4& def = osg::Vec4(1,1,0,1) );
+      void setDrawable( osg::Drawable* drawable );
 
     private:
+
+      osg::Drawable  *_drawable;
+
       Element(const Element&);// = delete
 
       virtual void childAdded( SGPropertyNode * parent,
diff --git a/src/Canvas/elements/group.cxx b/src/Canvas/elements/group.cxx
index 44b7166b7..94e0836a6 100644
--- a/src/Canvas/elements/group.cxx
+++ b/src/Canvas/elements/group.cxx
@@ -23,7 +23,7 @@ namespace canvas
 {
 
   //----------------------------------------------------------------------------
-  Group::Group(SGPropertyNode* node):
+  Group::Group(SGPropertyNode_ptr node):
     Element(node)
   {
 
@@ -39,7 +39,10 @@ namespace canvas
   void Group::update(double dt)
   {
     for( size_t i = 0; i < _children.size(); ++i )
-      _children[i]->update(dt);
+    {
+      if( _children[i] )
+        _children[i]->update(dt);
+    }
 
     Element::update(dt);
   }
@@ -47,19 +50,58 @@ namespace canvas
   //----------------------------------------------------------------------------
   void Group::childAdded(SGPropertyNode* child)
   {
+    boost::shared_ptr<Element> element;
+
     if( child->getNameString() == "text" )
-    {
-      _children.push_back( boost::shared_ptr<Element>(new Text(child)) );
-      _transform->addChild( _children.back()->getMatrixTransform() );
-    }
+      element.reset( new Text(child) );
+    else if( child->getNameString() == "group" )
+      element.reset( new Group(child) );
     else
-      std::cout << "New unknown child: " << child->getDisplayName() << std::endl;
+      SG_LOG
+      (
+        SG_GL,
+        SG_WARN,
+        "canvas::Group unknown child: " << child->getDisplayName()
+      );
+
+    if( !element )
+      return;
+
+    // Add to osg scene graph...
+    _transform->addChild( element->getMatrixTransform() );
+
+    // ...and build up canvas hierarchy
+    size_t index = child->getIndex();
+
+    if( index >= _children.size() )
+      _children.resize(index + 1);
+
+    _children[index] = element;
   }
 
   //----------------------------------------------------------------------------
   void Group::childRemoved(SGPropertyNode* child)
   {
+    if(    child->getNameString() == "text"
+        || child->getNameString() == "group" )
+    {
+      size_t index = child->getIndex();
 
+      if( index >= _children.size() )
+        SG_LOG
+        (
+          SG_GL,
+          SG_WARN,
+          "can't removed unknown child " << child->getDisplayName()
+        );
+      else
+      {
+        boost::shared_ptr<Element>& element = _children[index];
+        if( element )
+          _transform->removeChild(element->getMatrixTransform());
+        element.reset();
+      }
+    }
   }
 
 } // namespace canvas
diff --git a/src/Canvas/elements/group.hxx b/src/Canvas/elements/group.hxx
index ccfea07be..d13bb255c 100644
--- a/src/Canvas/elements/group.hxx
+++ b/src/Canvas/elements/group.hxx
@@ -26,17 +26,19 @@
 namespace canvas
 {
 
+  typedef boost::shared_ptr<Element> ElementPtr;
+
   class Group:
     public Element
   {
     public:
-      Group(SGPropertyNode* node);
+      Group(SGPropertyNode_ptr node);
       virtual ~Group();
 
       virtual void update(double dt);
 
     protected:
-      std::vector<boost::shared_ptr<Element> >  _children;
+      std::vector<ElementPtr> _children;
 
       virtual void childAdded(SGPropertyNode * child);
       virtual void childRemoved(SGPropertyNode * child);
diff --git a/src/Canvas/elements/text.cxx b/src/Canvas/elements/text.cxx
index af27cda07..6f7a961d5 100644
--- a/src/Canvas/elements/text.cxx
+++ b/src/Canvas/elements/text.cxx
@@ -17,26 +17,30 @@
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 #include "text.hxx"
-#include <osgText/Text>
+#include <Canvas/property_helper.hxx>
 
 #include <Main/globals.hxx>
 #include <Main/fg_props.hxx>
 
+#include <osgText/Text>
+
 namespace canvas
 {
 
   //----------------------------------------------------------------------------
-  Text::Text(SGPropertyNode* node):
+  Text::Text(SGPropertyNode_ptr node):
     Element(node, COLOR | COLOR_FILL | BOUNDING_BOX),
-    _text( new osgText::Text )
+    _text( new osgText::Text ),
+    _font_size( 0 ),
+    _font_aspect( 0 )
   {
-    _drawable = _text;
-    _text->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
+    setDrawable(_text);
+    _text->setCharacterSizeMode(osgText::Text::OBJECT_COORDS);
+    _text->setAxisAlignment(osgText::Text::USER_DEFINED_ROTATION);
+    _text->setRotation(osg::Quat(osg::PI, osg::X_AXIS));
 
-    // font size and property node
-    float character_size = _node->getFloatValue("size", 32);
-    _text->setCharacterSize( character_size );
-    _node->setFloatValue("size", character_size);
+    _font_size = getChildDefault<float>(_node, "character-size", 32);
+    _font_aspect = getChildDefault<float>(_node, "character-aspect-ratio", 1);
 
     osg::ref_ptr<osg::Geode> geode = new osg::Geode;
     geode->addDrawable(_text);
@@ -82,7 +86,30 @@ namespace canvas
   //----------------------------------------------------------------------------
   Text::~Text()
   {
+    if( _node )
+    {
+      _node->untie("alignment");
+      _node->untie("padding");
+      _node->untie("draw-mode");
+    }
+    _node = 0;
+  }
 
+  //----------------------------------------------------------------------------
+  void Text::update(double dt)
+  {
+    Element::update(dt);
+
+    if( _attributes_dirty & FONT_SIZE )
+    {
+      _text->setCharacterSize
+      (
+        _font_size->getFloatValue(),
+        _font_aspect->getFloatValue()
+      );
+
+      _attributes_dirty &= ~FONT_SIZE;
+    }
   }
 
   //----------------------------------------------------------------------------
@@ -123,16 +150,12 @@ namespace canvas
   //----------------------------------------------------------------------------
   void Text::childChanged(SGPropertyNode* child)
   {
-    if( child->getNameString() == "text" )
-      _text->setText(child->getStringValue());
-    else if( child->getNameString() == "size" )
-      _text->setCharacterSize( child->getFloatValue() );
+    if( _font_size == child || _font_aspect == child )
+      _attributes_dirty |= FONT_SIZE;
+    else if( child->getNameString() == "text" )
+      _text->setText( child->getStringValue() );
     else if( child->getNameString() == "font" )
       setFont( child->getStringValue() );
-    else
-      return;
-
-    _attributes_dirty |= BOUNDING_BOX;
   }
 
   //----------------------------------------------------------------------------
diff --git a/src/Canvas/elements/text.hxx b/src/Canvas/elements/text.hxx
index 38d508b00..38c7f1335 100644
--- a/src/Canvas/elements/text.hxx
+++ b/src/Canvas/elements/text.hxx
@@ -32,17 +32,28 @@ namespace canvas
     public Element
   {
     public:
-      Text(SGPropertyNode* node);
+      Text(SGPropertyNode_ptr node);
       virtual ~Text();
 
+      virtual void update(double dt);
+
       void setFont(const char* name);
 
       void setAlignment(const char* align);
       const char* getAlignment() const;
 
     protected:
+
+      enum TextAttributes
+      {
+        FONT_SIZE       = LAST_ATTRIBUTE << 1, // Font size and aspect ration
+      };
+
       osg::ref_ptr<osgText::Text>   _text;
 
+      SGPropertyNode_ptr  _font_size,
+                          _font_aspect;
+
       virtual void childChanged(SGPropertyNode * child);
       virtual void colorChanged(const osg::Vec4& color);
       virtual void colorFillChanged(const osg::Vec4& color);
diff --git a/src/Canvas/property_helper.cxx b/src/Canvas/property_helper.cxx
new file mode 100644
index 000000000..7bf65404e
--- /dev/null
+++ b/src/Canvas/property_helper.cxx
@@ -0,0 +1,47 @@
+// Some helper functions for accessing the property tree
+//
+// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#include "property_helper.hxx"
+#include <cassert>
+
+namespace canvas
+{
+  //----------------------------------------------------------------------------
+  void linkColorNodes( const char* name,
+                       SGPropertyNode* parent,
+                       std::vector<SGPropertyNode_ptr>& nodes,
+                       const osg::Vec4& def )
+  {
+    static const char* channels[] = {"red", "green", "blue", "alpha"};
+    static const size_t num_channels = sizeof(channels)/sizeof(channels[0]);
+
+    assert(name);
+    assert(parent);
+
+    // Don't tie to allow the usage of aliases
+    SGPropertyNode_ptr color = parent->getChild(name, 0, true);
+
+    // We need to be carefull do not get any unitialized nodes or null pointers
+    // because while creating the node a valueChanged event will be triggered.
+    nodes.clear();
+    nodes.reserve(num_channels);
+
+    for( size_t i = 0; i < num_channels; ++i )
+      nodes.push_back( getChildDefault(color, channels[i], def[i]) );
+  }
+}
diff --git a/src/Canvas/property_helper.hxx b/src/Canvas/property_helper.hxx
new file mode 100644
index 000000000..c62134ca1
--- /dev/null
+++ b/src/Canvas/property_helper.hxx
@@ -0,0 +1,67 @@
+// Some helper functions for accessing the property tree
+//
+// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifndef PROPERTY_HELPER_HXX_
+#define PROPERTY_HELPER_HXX_
+
+#include <simgear/props/props.hxx>
+#include <osg/Vec4>
+
+namespace canvas
+{
+
+  /**
+   * Get property node with default value
+   */
+  template<typename T>
+  SGPropertyNode* getChildDefault( SGPropertyNode* parent,
+                                   const char* name,
+                                   T def_val )
+  {
+    SGPropertyNode* node = parent->getNode(name);
+    if( node )
+      // also set value for existing nodes to enforce type...
+      def_val = getValue<T>(node);
+    else
+      node = parent->getChild(name, 0, true);
+
+    setValue(node, def_val);
+    return node;
+  }
+
+  /**
+   * @param name    Name of color node
+   * @param parent  Parent for color channel nodes
+   * @param nodes   Vector to push color nodes into
+   * @param def     Default color
+   *
+   * <name>
+   *   <red type="float">def[0] or existing value</red>
+   *   <green type="float">def[1] or existing value</green>
+   *   <blue type="float">def[2] or existing value</blue>
+   *   <alpha type="float">def[3] or existing value</alpha>
+   * </name>
+   */
+  void linkColorNodes( const char* name,
+                       SGPropertyNode* parent,
+                       std::vector<SGPropertyNode_ptr>& nodes,
+                       const osg::Vec4& def = osg::Vec4(0,0,0,0) );
+
+} // namespace canvas
+
+#endif /* PROPERTY_HELPER_HXX_ */
diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx
index ae57786a6..78915e725 100644
--- a/src/Main/fg_init.cxx
+++ b/src/Main/fg_init.cxx
@@ -29,15 +29,9 @@
 #include <stdlib.h>
 #include <string.h>             // strcmp()
 
-#if defined( unix ) || defined( __CYGWIN__ )
-#  include <unistd.h>           // for gethostname()
-#endif
 #ifdef _WIN32
-#  include <direct.h>           // for getcwd()
-#  define getcwd _getcwd
 #  include <io.h>               // isatty()
 #  define isatty _isatty
-#  include "winsock2.h"		// for gethostname()
 #endif
 
 // work around a stdc++ lib bug in some versions of linux, but doesn't
@@ -1027,12 +1021,11 @@ bool fgInitGeneral() {
 
     globals->set_browser(fgGetString("/sim/startup/browser-app", "firefox %u"));
 
-    char buf[512], *cwd = getcwd(buf, 511);
-    buf[511] = '\0';
+    simgear::Dir cwd(simgear::Dir::current());
     SGPropertyNode *curr = fgGetNode("/sim", true);
     curr->removeChild("fg-current", 0, false);
     curr = curr->getChild("fg-current", 0, true);
-    curr->setStringValue(cwd ? cwd : "");
+    curr->setStringValue(cwd.path().str());
     curr->setAttribute(SGPropertyNode::WRITE, false);
 
     fgSetBool("/sim/startup/stdout-to-terminal", isatty(1) != 0 );