)
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
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;
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;
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);
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
//----------------------------------------------------------------------------
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());
}
//----------------------------------------------------------------------------
--- /dev/null
+/// 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 );
+}
#include <simgear/props/props.hxx>
#include <simgear/structure/SGWeakReferenced.hxx>
-#include <boost/call_traits.hpp>
-
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 )