From: Thomas Geymayer Date: Thu, 29 May 2014 14:46:11 +0000 (+0200) Subject: Canvas: store data inside canvas and elements. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=7c31654b3a570b275f224e143399968cf9bde719;p=flightgear.git Canvas: store data inside canvas and elements. - jQuery/HTML5 like .data() method on Canvas and Elements to store custom data in the property tree. - CustomEvent takes additional parameter hash with 'detail' data stored in event. --- diff --git a/src/Scripting/NasalCanvas.cxx b/src/Scripting/NasalCanvas.cxx index 0c705e230..2e0b0c034 100644 --- a/src/Scripting/NasalCanvas.cxx +++ b/src/Scripting/NasalCanvas.cxx @@ -62,6 +62,7 @@ struct CustomEventDetailWrapper; typedef SGSharedPtr CustomEventDetailPtr; typedef nasal::Ghost NasalCustomEventDetail; +typedef nasal::Ghost NasalPropertyBasedElement; typedef nasal::Ghost NasalCanvas; typedef nasal::Ghost NasalElement; typedef nasal::Ghost NasalGroup; @@ -88,6 +89,11 @@ SGPropertyNode* from_nasal_helper(naContext c, naRef ref, SGPropertyNode**) return props; } +sc::CanvasWeakPtr from_nasal_helper(naContext c, naRef ref, sc::CanvasWeakPtr const*) +{ + return nasal::from_nasal(c, ref); +} + CanvasMgr& requireCanvasMgr(naContext c) { CanvasMgr* canvas_mgr = @@ -202,6 +208,90 @@ naRef f_groupGetElementById(sc::Group& group, const nasal::CallContext& ctx) ); } +static void propElementSetData( simgear::PropertyBasedElement& el, + const std::string& name, + naContext c, + naRef ref ) +{ + if( naIsNil(ref) ) + return el.removeDataProp(name); + + std::string val = nasal::from_nasal(c, ref); + + char* end = NULL; + + long val_long = strtol(val.c_str(), &end, 10); + if( !*end ) + return el.setDataProp(name, val_long); + + double val_double = strtod(val.c_str(), &end); + if( !*end ) + return el.setDataProp(name, val_double); + + el.setDataProp(name, val); +} + +/** + * Accessor for HTML5 data properties. + * + * # set single property: + * el.data("myKey", 5); + * + * # set multiple properties + * el.data({myProp1: 12, myProp2: "test"}); + * + * # get value of properties + * el.data("myKey"); # 5 + * el.data("myProp2"); # "test" + * + * # remove a single property + * el.data("myKey", nil); + * + * # remove multiple properties + * el.data({myProp1: nil, myProp2: nil}); + * + * # set and remove multiple properties + * el.data({newProp: "some text...", removeProp: nil}); + * + * + * @see http://api.jquery.com/data/ + */ +static naRef f_propElementData( simgear::PropertyBasedElement& el, + const nasal::CallContext& ctx ) +{ + if( ctx.isHash(0) ) + { + // Add/delete properties given as hash + nasal::Hash obj = ctx.requireArg(0); + for(nasal::Hash::iterator it = obj.begin(); it != obj.end(); ++it) + propElementSetData(el, it->getKey(), ctx.c, it->getValue()); + + return ctx.to_nasal(&el); + } + + std::string name = ctx.getArg(0); + if( !name.empty() ) + { + if( ctx.argc == 1 ) + { + // name + additional argument -> add/delete property + SGPropertyNode* node = el.getDataProp(name); + if( !node ) + return naNil(); + + return ctx.to_nasal( node->getStringValue() ); + } + else + { + // only name -> get property + propElementSetData(el, name, ctx.c, ctx.requireArg(1)); + return ctx.to_nasal(&el); + } + } + + return naNil(); +} + template naRef f_eventGetModifier(sc::MouseEvent& event, naContext) { @@ -214,10 +304,18 @@ static naRef f_createCustomEvent(const nasal::CallContext& ctx) if( type.empty() ) return naNil(); - simgear::StringMap data = ctx.getArg(1); + simgear::StringMap detail; + if( ctx.isHash(1) ) + { + nasal::Hash const& cfg = ctx.requireArg(1); + naRef na_detail = cfg.get("detail"); + if( naIsHash(na_detail) ) + detail = ctx.from_nasal(na_detail); + } + return NasalCustomEvent::create( ctx.c, - sc::CustomEventPtr(new sc::CustomEvent(type, data)) + sc::CustomEventPtr(new sc::CustomEvent(type, detail)) ); } @@ -271,6 +369,11 @@ naRef to_nasal_helper(naContext c, const sc::ElementWeakPtr& el) return NasalElement::create(c, el.lock()); } +naRef to_nasal_helper(naContext c, const sc::CanvasWeakPtr& canvas) +{ + return NasalCanvas::create(c, canvas.lock()); +} + naRef initNasalCanvas(naRef globals, naContext c) { using osgGA::GUIEventAdapter; @@ -306,16 +409,22 @@ naRef initNasalCanvas(naRef globals, naContext c) .member("metaKey", &f_eventGetModifier) .member("click_count", &sc::MouseEvent::getCurrentClickCount); + NasalPropertyBasedElement::init("PropertyBasedElement") + .method("data", &f_propElementData); NasalCanvas::init("Canvas") + .bases() .member("_node_ghost", &elementGetNode) .member("size_x", &sc::Canvas::getSizeX) .member("size_y", &sc::Canvas::getSizeY) .method("_createGroup", &f_canvasCreateGroup) .method("_getGroup", &sc::Canvas::getGroup) - .method("addEventListener", &sc::Canvas::addEventListener); + .method("addEventListener", &sc::Canvas::addEventListener) + .method("dispatchEvent", &sc::Canvas::dispatchEvent); NasalElement::init("canvas.Element") + .bases() .member("_node_ghost", &elementGetNode) .method("_getParent", &sc::Element::getParent) + .method("_getCanvas", &sc::Element::getCanvas) .method("addEventListener", &sc::Element::addEventListener) .method("dispatchEvent", &sc::Element::dispatchEvent) .method("getBoundingBox", &sc::Element::getBoundingBox)