]> git.mxchange.org Git - simgear.git/commitdiff
canvas::Element: setter/getter for HTML5 style data-* properties.
authorThomas Geymayer <tomgey@gmail.com>
Wed, 28 May 2014 16:09:34 +0000 (18:09 +0200)
committerThomas Geymayer <tomgey@gmail.com>
Wed, 28 May 2014 16:11:32 +0000 (18:11 +0200)
simgear/canvas/elements/CMakeLists.txt
simgear/canvas/elements/CanvasElement.cxx
simgear/canvas/elements/CanvasElement.hxx
simgear/canvas/elements/CanvasGroup.cxx
simgear/canvas/elements/canvas_element_test.cpp [new file with mode: 0644]
simgear/props/PropertyBasedElement.hxx

index bd21c13d8fb123b89a49986dbdc6f8b57cd10a9a..2b537c0c63c051276da88dd88abc56deef8fa088 100644 (file)
@@ -23,4 +23,9 @@ set(SOURCES
 )
 
 simgear_scene_component(canvas-elements canvas/elements "${SOURCES}" "${HEADERS}")
-simgear_component(canvas-elements/detail canvas/elements/detail "" "${DETAIL_HEADERS}")
\ No newline at end of file
+simgear_component(canvas-elements/detail canvas/elements/detail "" "${DETAIL_HEADERS}")
+
+add_boost_test(canvas_element
+  SOURCES canvas_element_test.cpp
+  LIBRARIES ${TEST_LIBS}
+)
\ No newline at end of file
index 9bb75b1281d702f3de6b65dd1a1fdcfdc3ab7a16..1c506fbc6d002e68d812860e75fab6482363efe7 100644 (file)
@@ -437,7 +437,8 @@ namespace canvas
       else if( boost::starts_with(name, "blend-") )
         return (void)(_attributes_dirty |= BLEND_FUNC);
     }
-    else if(   parent->getParent() == _node
+    else if(   parent
+            && parent->getParent() == _node
             && parent->getNameString() == NAME_TRANSFORM )
     {
       _attributes_dirty |= TRANSFORM;
@@ -634,6 +635,74 @@ namespace canvas
     return m;
   }
 
+  //----------------------------------------------------------------------------
+  static const std::string DATA_PREFIX("data-");
+
+  //----------------------------------------------------------------------------
+  std::string Element::dataPropToAttrName(const std::string& name)
+  {
+    // http://www.w3.org/TR/html5/dom.html#attr-data-*
+    //
+    // 3. Insert the string data- at the front of name.
+
+    std::string attr_name;
+    for( std::string::const_iterator cur = name.begin();
+                                     cur != name.end();
+                                   ++cur )
+    {
+      // If name contains a "-" (U+002D) character followed by a lowercase ASCII
+      // letter, throw a SyntaxError exception and abort these steps.
+      if( *cur == '-' )
+      {
+        std::string::const_iterator next = cur + 1;
+        if( next != name.end() && islower(*next) )
+          return std::string();
+      }
+
+      // For each uppercase ASCII letter in name, insert a "-" (U+002D)
+      // character before the character and replace the character with the same
+      // character converted to ASCII lowercase.
+      if( isupper(*cur) )
+      {
+        attr_name.push_back('-');
+        attr_name.push_back( tolower(*cur) );
+      }
+      else
+        attr_name.push_back( *cur );
+    }
+    return DATA_PREFIX + attr_name;
+  }
+
+  //----------------------------------------------------------------------------
+  std::string Element::attrToDataPropName(const std::string& name)
+  {
+    // http://www.w3.org/TR/html5/dom.html#attr-data-*
+    //
+    // For each "-" (U+002D) character in the name that is followed by a
+    // lowercase ASCII letter, remove the "-" (U+002D) character and replace the
+    // character that followed it by the same character converted to ASCII
+    // uppercase.
+
+    if( !boost::starts_with(name, DATA_PREFIX) )
+      return std::string();
+
+    std::string data_name;
+    for( std::string::const_iterator cur = name.begin() + DATA_PREFIX.length();
+                                     cur != name.end();
+                                   ++cur )
+    {
+      std::string::const_iterator next = cur + 1;
+      if( *cur == '-' && next != name.end() && islower(*next) )
+      {
+        data_name.push_back( toupper(*next) );
+        cur = next;
+      }
+      else
+        data_name.push_back(*cur);
+    }
+    return data_name;
+  }
+
   //----------------------------------------------------------------------------
   Element::StyleSetters Element::_style_setters;
 
index f8b4bcf57a0c31d3bb6ad7531fbe76df64ea4f12..9a85a23cf058e7f3af3bf39ef6106c6fead4e204 100644 (file)
@@ -104,6 +104,30 @@ namespace canvas
       bool addEventListener(const std::string& type, const EventListener& cb);
       virtual void clearEventListener();
 
+      template<class T>
+      void setDataProp( const std::string& name,
+                        const T& val )
+      {
+        const std::string& attr = dataPropToAttrName(name);
+        if( !attr.empty() )
+          set<T>(attr, val);
+        else
+          SG_LOG(SG_GENERAL, SG_WARN, "Invalid data-prop name: " << name);
+      }
+
+      template<class T>
+      T getDataProp( const std::string& name,
+                     const T& def = T() )
+      {
+        const std::string& attr = dataPropToAttrName(name);
+        if( !attr.empty() )
+          return get<T>(attr, def);
+        else
+          SG_LOG(SG_GENERAL, SG_WARN, "Invalid data-prop name: " << name);
+
+        return def;
+      }
+
       virtual bool accept(EventVisitor& visitor);
       virtual bool ascend(EventVisitor& visitor);
       virtual bool traverse(EventVisitor& visitor);
@@ -195,12 +219,15 @@ namespace canvas
         ElementPtr
       >::type create( const CanvasWeakPtr& canvas,
                       const SGPropertyNode_ptr& node,
-                      const Style& style,
-                      Element* parent )
+                      const Style& style = Style(),
+                      Element* parent = NULL )
       {
         return ElementPtr( new Derived(canvas, node, style, parent) );
       }
 
+      static std::string dataPropToAttrName(const std::string& name);
+      static std::string attrToDataPropName(const std::string& name);
+
     protected:
 
       enum Attributes
index ce86320abe1e4ab09eb99af339ac3b0af2bc16da..e2c888855b6bab2171e3074b77dcab642b270f36 100644 (file)
@@ -320,10 +320,12 @@ namespace canvas
   //----------------------------------------------------------------------------
   void Group::childChanged(SGPropertyNode* node)
   {
-    if(    node->getParent()->getParent() == _node
+    SGPropertyNode* parent = node->getParent();
+    SGPropertyNode* grand_parent = parent ? parent->getParent() : NULL;
+
+    if(    grand_parent == _node
         && node->getNameString() == "z-index" )
-      return handleZIndexChanged( getChild(node->getParent()),
-                                  node->getIntValue() );
+      return handleZIndexChanged(getChild(parent), node->getIntValue());
   }
 
   //----------------------------------------------------------------------------
diff --git a/simgear/canvas/elements/canvas_element_test.cpp b/simgear/canvas/elements/canvas_element_test.cpp
new file mode 100644 (file)
index 0000000..fe3c2ee
--- /dev/null
@@ -0,0 +1,54 @@
+/// Unit tests for canvas::Element
+#define BOOST_TEST_MODULE canvas
+#include <BoostTestTargetConfig.h>
+
+#include "CanvasElement.hxx"
+#include "CanvasGroup.hxx"
+
+namespace sc = simgear::canvas;
+
+BOOST_AUTO_TEST_CASE( attr_data )
+{
+  // http://www.w3.org/TR/html5/dom.html#attr-data-*
+
+#define SG_CHECK_ATTR2PROP(attr, prop)\
+  BOOST_CHECK_EQUAL(sc::Element::attrToDataPropName(attr), prop)
+
+  // If name starts with "data-", for each "-" (U+002D) character in the name
+  // that is followed by a lowercase ASCII letter, remove the "-" (U+002D)
+  // character and replace the character that followed it by the same character
+  // converted to ASCII uppercase.
+
+  SG_CHECK_ATTR2PROP("no-data", "");
+  SG_CHECK_ATTR2PROP("data-blub", "blub");
+  SG_CHECK_ATTR2PROP("data-blub-x-y", "blubXY");
+  SG_CHECK_ATTR2PROP("data-blub-x-y-", "blubXY-");
+
+#undef SG_CHECK_ATTR2PROP
+
+#define SG_CHECK_PROP2ATTR(prop, attr)\
+  BOOST_CHECK_EQUAL(sc::Element::dataPropToAttrName(prop), attr)
+
+  // If name contains a "-" (U+002D) character followed by a lowercase ASCII
+  // letter, throw a SyntaxError exception (empty string) and abort these steps.
+  // For each uppercase ASCII letter in name, insert a "-" (U+002D) character
+  // before the character and replace the character with the same character
+  // converted to ASCII lowercase.
+  // Insert the string "data-" at the front of name.
+
+  SG_CHECK_PROP2ATTR("test", "data-test");
+  SG_CHECK_PROP2ATTR("testIt", "data-test-it");
+  SG_CHECK_PROP2ATTR("testIt-Hyphen", "data-test-it--hyphen");
+  SG_CHECK_PROP2ATTR("-test", "");
+  SG_CHECK_PROP2ATTR("test-", "data-test-");
+
+#undef SG_CHECK_PROP2ATTR
+
+  SGPropertyNode_ptr node = new SGPropertyNode;
+  sc::ElementPtr el =
+    sc::Element::create<sc::Group>(sc::CanvasWeakPtr(), node);
+
+  el->setDataProp("myData", 3);
+  BOOST_CHECK_EQUAL( el->getDataProp<int>("myData"), 3 );
+  BOOST_CHECK_EQUAL( node->getIntValue("data-my-data"), 3 );
+}
index a0682fd04bd2a33fb6faaf4aa613d5b17a46112a..dcaceaf028724b92e93973f19aed4552bb4826d4 100644 (file)
@@ -22,8 +22,6 @@
 #include <simgear/props/props.hxx>
 #include <simgear/structure/SGWeakReferenced.hxx>
 
-#include <boost/call_traits.hpp>
-
 namespace simgear
 {
 
@@ -59,14 +57,14 @@ namespace simgear
 
       template<class T>
       void set( const std::string& name,
-                typename boost::call_traits<T>::param_type val )
+                const T& val )
       {
         setValue(_node->getNode(name, true), val);
       }
 
       template<class T>
       T get( const std::string& name,
-             typename boost::call_traits<T>::param_type def = T() )
+             const T& def = T() )
       {
         SGPropertyNode const* child = _node->getNode(name);
         if( !child )