X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FScripting%2FNasalCanvas.cxx;h=32aa4f84dba6dade91338c2f1c303bfff366777a;hb=7f43a09fc57f542a33480bc995f2c78c7c971a6a;hp=dba2851476b818302d2608296f97865d270e29a8;hpb=863cd6a2902b97c3328a6bd4cd41b9182b78aadd;p=flightgear.git diff --git a/src/Scripting/NasalCanvas.cxx b/src/Scripting/NasalCanvas.cxx index dba285147..32aa4f84d 100644 --- a/src/Scripting/NasalCanvas.cxx +++ b/src/Scripting/NasalCanvas.cxx @@ -22,838 +22,250 @@ # include "config.h" #endif -#include -#include - #include "NasalCanvas.hxx" #include +#include +#include #include
+#include -//#include -#include -#include -#include -#include -#include #include #include #include #include +#include +#include -static naRef elementPrototype; -static naRef propsNodePrototype; +#include +#include +#include +#include extern naRef propNodeGhostCreate(naContext c, SGPropertyNode* n); -static void hashset(naContext c, naRef hash, const char* key, naRef val) -{ - naRef s = naNewString(c); - naStr_fromdata(s, (char*)key, strlen(key)); - naHash_set(hash, s, val); -} +namespace sc = simgear::canvas; -template -typename boost::enable_if, naRef>::type -convertToNasal(T val) +template +naRef elementGetNode(naContext c, Element& element) { - return naNum(val); + return propNodeGhostCreate(c, element.getProps()); } -//void initCanvasPython() -//{ -// using namespace boost::python; -// class_("Canvas"); -//} - -namespace sc = simgear::canvas; +typedef nasal::Ghost NasalEvent; +typedef nasal::Ghost NasalMouseEvent; +typedef nasal::Ghost NasalCanvas; +typedef nasal::Ghost NasalElement; +typedef nasal::Ghost NasalGroup; +typedef nasal::Ghost NasalText; +typedef nasal::Ghost NasalWindow; -naRef canvasGetTexture(naContext c, sc::Canvas* canvas) +naRef to_nasal_helper(naContext c, const osg::BoundingBox& bb) { - //{ parents : [Node], _g : node } - naRef parents = naNewVector(c); - naVec_append(parents, propsNodePrototype); + std::vector bb_vec(4); + bb_vec[0] = bb._min.x(); + bb_vec[1] = bb._min.y(); + bb_vec[2] = bb._max.x(); + bb_vec[3] = bb._max.y(); - naRef node = naNewHash(c); - hashset(c, node, "parents", parents); - hashset(c, node, "_g", propNodeGhostCreate(c, canvas->getProps())); - - return node; + return nasal::to_nasal(c, bb_vec); } -namespace nasal +SGPropertyNode* from_nasal_helper(naContext c, naRef ref, SGPropertyNode**) { + SGPropertyNode* props = ghostToPropNode(ref); + if( !props ) + naRuntimeError(c, "Not a SGPropertyNode ghost."); - template - struct class_traits - { - typedef boost::false_type::type is_shared; - typedef T raw_type; - }; - - template - struct class_traits > - { - typedef boost::true_type::type is_shared; - typedef T raw_type; - }; - - template - struct class_traits > - { - typedef boost::true_type::type is_shared; - typedef T raw_type; - }; - - template - struct class_traits > - { - typedef boost::true_type::type is_shared; - typedef T raw_type; - }; - - template - struct SharedPointerPolicy - { - typedef typename class_traits::raw_type raw_type; - - /** - * Create a shared pointer on the heap to handle the reference counting for - * the passed shared pointer while it is used in Nasal space. - */ - static T* createInstance(const T& ptr) - { - return new T(ptr); - } - - static raw_type* getRawPtr(void* ptr) - { - return static_cast(ptr)->get(); - } - }; - - template - struct RawPointerPolicy - { - typedef typename class_traits::raw_type raw_type; - - static T* createInstance() - { - return new T(); - } - - static raw_type* getRawPtr(void* ptr) - { - BOOST_STATIC_ASSERT((boost::is_same::value)); - return static_cast(ptr); - } - }; - - class class_metadata - { - public: - void addNasalBase(const naRef& parent) - { - assert( naIsHash(parent) ); - _parents.push_back(parent); - } - - protected: - const std::string _name; - naGhostType _ghost_type; - std::vector _base_classes; - std::vector _parents; - - explicit class_metadata(const std::string& name): - _name(name) - { - - } - - void addBaseClass(class_metadata* base) - { - assert(base); - std::cout << _name << ": addBase(" << base->_name << ")" << std::endl; - _base_classes.push_back(base); - } - - naRef getParents(naContext c) - { - naRef parents = naNewVector(c); - for(size_t i = 0; i < _parents.size(); ++i) - naVec_append(parents, _parents[i]); - return parents; - } - }; - - /** - * Class for exposing C++ objects to Nasal - */ - template - class class_: - public class_metadata, - protected boost::mpl::if_< typename class_traits::is_shared, - SharedPointerPolicy, - RawPointerPolicy >::type - { - private: - typedef typename class_traits::raw_type raw_type; - - public: - - typedef boost::function getter_t; - typedef std::map GetterMap; - - static class_& init(const std::string& name) - { - getSingletonHolder().reset( new class_(name) ); - return *getSingletonPtr(); - } - - static naRef f_create(naContext c, naRef me, int argc, naRef* args) - { - return create(c); - } - - static naRef create( naContext c ) - { - return makeGhost(c, class_::createInstance()); - } - - // TODO use variadic template when supporting C++11 - template - static naRef create( naContext c, const A1& a1 ) - { - return makeGhost(c, class_::createInstance(a1)); - } - - class_& bases(const naRef& parent) - { - addNasalBase(parent); - return *this; - } - - template - typename boost::enable_if - < boost::is_convertible, - class_ - >::type& - bases() - { - Base* base = Base::getSingletonPtr(); - addBaseClass( base ); - - // Replace any getter that is not available in the current class. - // TODO check if this is the correct behavior of function overriding - const typename Base::GetterMap& base_getter = base->getGetter(); - for( typename Base::GetterMap::const_iterator getter = - base_getter.begin(); - getter != base_getter.end(); - ++getter ) - { - if( _getter.find(getter->first) == _getter.end() ) - _getter.insert( *getter ); - } - - return *this; - } - - template - typename boost::enable_if_c - < !boost::is_convertible< Type, class_metadata>::value, - class_ - >::type& - bases() - { - return bases< class_ >(); - } - - template - class_& def( const std::string& field, - Var (raw_type::*getter)() const ) - { - _getter[field] = boost::bind( &convertToNasal, - boost::bind(getter, _2) ); - return *this; - } - - class_& def_readonly( const std::string& field, - getter_t getter ) - { - _getter[field] = getter; - return *this; - } - - /** - * Data member - */ - template - class_& def_readonly( const std::string& field, - Var raw_type::*var ) - { - _getter[field] = boost::bind( &convertToNasal, - boost::bind(var, _2) ); - return *this; - } - - static class_* getSingletonPtr() - { - return getSingletonHolder().get(); - } - - const GetterMap& getGetter() const - { - return _getter; - } - - private: - - typedef std::auto_ptr class_ptr; - GetterMap _getter; - - explicit class_(const std::string& name): - class_metadata( name ) - { - _ghost_type.destroy = &destroyGhost; - _ghost_type.name = _name.c_str(); - _ghost_type.get_member = &getMember; - _ghost_type.set_member = 0; - } - - static class_ptr& getSingletonHolder() - { - static class_ptr instance; - return instance; - } - - static naRef makeGhost(naContext c, void *ptr) - { - std::cout << "makeGhost " << ptr << std::endl; - return naNewGhost2(c, &getSingletonPtr()->_ghost_type, ptr); - } - - static void destroyGhost(void *ptr) - { - std::cout << "destroyGhost " << ptr << std::endl; - delete (T*)ptr; - } - - static const char* getMember(naContext c, void* g, naRef field, naRef* out) - { - const std::string key = naStr_data(field); - if( key == "parents" ) - { - *out = getSingletonPtr()->getParents(c); - return ""; - } - - typename GetterMap::iterator getter = - getSingletonPtr()->_getter.find(key); - - if( getter == getSingletonPtr()->_getter.end() ) - return 0; - - *out = getter->second(c, class_::getRawPtr(g)); - return ""; - } - }; + return props; } -struct Base +CanvasMgr& requireCanvasMgr(naContext c) { - int getInt() const - { - return 8; - } -}; - -struct Test: - public Base -{ - Test(): x(1) {} - int x; -}; + CanvasMgr* canvas_mgr = + static_cast(globals->get_subsystem("Canvas")); + if( !canvas_mgr ) + naRuntimeError(c, "Failed to get Canvas subsystem"); -typedef nasal::class_ NasalCanvas; + return *canvas_mgr; +} -void initCanvas() +GUIMgr& requireGUIMgr(naContext c) { + GUIMgr* mgr = + static_cast(globals->get_subsystem("CanvasGUI")); + if( !mgr ) + naRuntimeError(c, "Failed to get CanvasGUI subsystem"); - NasalCanvas::init("Canvas") - .def_readonly("texture", &canvasGetTexture) - .def("size_x", &sc::Canvas::getSizeX) - .def("size_y", &sc::Canvas::getSizeY); - nasal::class_::init("canvas.Element"); - nasal::class_::init("canvas.Group") - .bases(); - - nasal::class_::init("BaseClass") - .def("int", &Base::getInt); - nasal::class_::init("TestClass") - .bases() - .def_readonly("x", &Test::x); + return *mgr; } /** - * A Nasal Hash + * Create new Canvas and get ghost for it. */ -class Hash +static naRef f_createCanvas(const nasal::CallContext& ctx) { - public: - - /** - * Initialize from an existing Nasal Hash - * - * @param hash Existing Nasal Hash - * @param c Nasal context - */ - Hash(const naRef& hash, naContext c): - _hash(hash), - _context(c) - { - assert( naIsHash(_hash) ); - } - - void set(const std::string& name, naRef val) - { - naHash_set(_hash, stringToNasal(name), val); - } - - void set(const std::string& name, naCFunction func) - { - set(name, naNewFunc(_context, naNewCCode(_context, func))); - } - - void set(const std::string& name, const std::string& str) - { - set(name, stringToNasal(str)); - } - - void set(const std::string& name, double num) - { - set(name, naNum(num)); - } - - /** - * Create a new child hash (module) - * - * @param name Name of the new hash inside this hash - */ - Hash createHash(const std::string& name) - { - naRef hash = naNewHash(_context); - set(name, hash); - return Hash(hash, _context); - } - - protected: - naRef _hash; - naContext _context; - - naRef stringToNasal(const std::string& str) - { - naRef s = naNewString(_context); - naStr_fromdata(s, str.c_str(), str.size()); - return s; - } -}; + return NasalCanvas::create(ctx.c, requireCanvasMgr(ctx.c).createCanvas()); +} /** - * Class for exposing C++ objects to Nasal + * Create new Window and get ghost for it. */ -template -class NasalObject -{ - public: - // TODO use variadic template when supporting C++11 - template - static naRef create( naContext c, const A1& a1 ) - { - return makeGhost(c, new T(a1)); - } - - template - static naRef create( naContext c, const A1& a1, - const A2& a2 ) - { - return makeGhost(c, new T(a1, a2)); - } - - template - static naRef create( naContext c, const A1& a1, - const A2& a2, - const A3& a3 ) - { - return makeGhost(c, new T(a1, a2, a3)); - } - - template - static naRef create( naContext c, const A1& a1, - const A2& a2, - const A3& a3, - const A4& a4 ) - { - return makeGhost(c, new T(a1, a2, a3, a4)); - } - - template - static naRef create( naContext c, const A1& a1, - const A2& a2, - const A3& a3, - const A4& a4, - const A5& a5 ) - { - return makeGhost(c, new T(a1, a2, a3, a4, a5)); - } - - // TODO If you need more arguments just do some copy&paste :) - - static Derived& getInstance() - { - static Derived instance; - return instance; - } - - void setParent(const naRef& parent) - { - // TODO check if we need to take care of reference counting/gc - _parents.resize(1); - _parents[0] = parent; - } - - protected: - - // TODO switch to boost::/std::function (with C++11 lambdas this can make - // adding setters easier and shorter) - typedef naRef (Derived::*getter_t)(naContext, const T&); - typedef std::map GetterMap; - - const std::string _ghost_name; - std::vector _parents; - GetterMap _getter; - - NasalObject(const std::string& ghost_name): - _ghost_name( ghost_name ) - { - _ghost_type.destroy = &destroyGhost; - _ghost_type.name = _ghost_name.c_str(); - _ghost_type.get_member = &Derived::getMember; - _ghost_type.set_member = 0; - - _getter["parents"] = &NasalObject::getParents; - } - - naRef getParents(naContext c, const T&) - { - naRef parents = naNewVector(c); - for(size_t i = 0; i < _parents.size(); ++i) - naVec_append(parents, _parents[i]); - return parents; - } - - static naRef makeGhost(naContext c, void *ptr) - { - std::cout << "create " << ptr << std::endl; - return naNewGhost2(c, &(getInstance()._ghost_type), ptr); - } - - static void destroyGhost(void *ptr) - { - std::cout << "destroy " << ptr << std::endl; - delete (T*)ptr; - } - - static const char* getMember(naContext c, void* g, naRef field, naRef* out) - { - typename GetterMap::iterator getter = - getInstance()._getter.find(naStr_data(field)); - - if( getter == getInstance()._getter.end() ) - return 0; - - *out = (getInstance().*getter->second)(c, *static_cast(g)); - return ""; - } - - private: - - naGhostType _ghost_type; - -}; - -static naRef stringToNasal(naContext c, const std::string& s) -{ - return naStr_fromdata(naNewString(c), - const_cast(s.c_str()), - s.length()); -} - -typedef osg::ref_ptr GUIEventPtr; - -class NasalCanvasEvent: - public NasalObject -{ - public: - - NasalCanvasEvent(): - NasalObject("CanvasEvent") - { - _getter["type"] = &NasalCanvasEvent::getEventType; - } - - naRef getEventType(naContext c, const GUIEventPtr& event) - { -#define RET_EVENT_STR(type, str)\ - case osgGA::GUIEventAdapter::type:\ - return stringToNasal(c, str); - - switch( event->getEventType() ) - { - RET_EVENT_STR(PUSH, "push"); - RET_EVENT_STR(RELEASE, "release"); - RET_EVENT_STR(DOUBLECLICK, "double-click"); - RET_EVENT_STR(DRAG, "drag"); - RET_EVENT_STR(MOVE, "move"); - RET_EVENT_STR(SCROLL, "scroll"); - RET_EVENT_STR(KEYUP, "key-up"); - RET_EVENT_STR(KEYDOWN, "key-down"); - -#undef RET_EVENT_STR - - default: - return naNil(); - } - } -}; - -//using simgear::canvas::CanvasPtr; -// -///** -// * Expose Canvas to Nasal -// */ -//class NasalCanvas: -// public NasalObject -//{ -// public: -// -// NasalCanvas(): -// NasalObject("Canvas") -// { -// _getter["texture"] = &NasalCanvas::getTexture; -// _getter["size_x"] = &NasalCanvas::getSizeX; -// _getter["size_y"] = &NasalCanvas::getSizeY; -// } -// -// static naRef f_create(naContext c, naRef me, int argc, naRef* args) -// { -// std::cout << "NasalCanvas::create" << std::endl; -// -// CanvasMgr* canvas_mgr = -// static_cast(globals->get_subsystem("Canvas")); -// if( !canvas_mgr ) -// return naNil(); -// -// return create(c, canvas_mgr->createCanvas()); -// } -// -// static naRef f_setPrototype(naContext c, naRef me, int argc, naRef* args) -// { -// if( argc != 1 || !naIsHash(args[0]) ) -// naRuntimeError(c, "Invalid argument(s)"); -// -// getInstance().setParent(args[0]); -// -// return naNil(); -// } -// -// naRef getTexture(naContext c, const CanvasPtr& canvas) -// { -// //{ parents : [Node], _g : node } -// naRef parents = naNewVector(c); -// naVec_append(parents, propsNodePrototype); -// -// naRef node = naNewHash(c); -// hashset(c, node, "parents", parents); -// hashset(c, node, "_g", propNodeGhostCreate(c, canvas->getProps())); -// -// return node; -// } -// -// naRef getSizeX(naContext c, const CanvasPtr& canvas) -// { -// return naNum(canvas->getSizeX()); -// } -// -// naRef getSizeY(naContext c, const CanvasPtr& canvas) -// { -// return naNum(canvas->getSizeY()); -// } -//}; - -static void elementGhostDestroy(void* g); - -static const char* elementGhostGetMember(naContext c, void* g, naRef field, naRef* out); -static void elementGhostSetMember(naContext c, void* g, naRef field, naRef value); -naGhostType ElementGhostType = { elementGhostDestroy, "canvas.element", - elementGhostGetMember, elementGhostSetMember }; - -static simgear::canvas::Element* elementGhost(naRef r) +static naRef f_createWindow(const nasal::CallContext& ctx) { - if (naGhost_type(r) == &ElementGhostType) - return (simgear::canvas::Element*) naGhost_ptr(r); - return 0; + return NasalWindow::create + ( + ctx.c, + requireGUIMgr(ctx.c).createWindow( ctx.getArg(0) ) + ); } -static void elementGhostDestroy(void* g) +/** + * Get ghost for existing Canvas. + */ +static naRef f_getCanvas(naContext c, naRef me, int argc, naRef* args) { -} + nasal::CallContext ctx(c, argc, args); + SGPropertyNode& props = *ctx.requireArg(0); + CanvasMgr& canvas_mgr = requireCanvasMgr(c); -static const char* eventGhostGetMember(naContext c, void* g, naRef field, naRef* out) -{ - const char* fieldName = naStr_data(field); - osgGA::GUIEventAdapter* gea = (osgGA::GUIEventAdapter*) g; - - if (!strcmp(fieldName, "windowX")) *out = naNum(gea->getWindowX()); - else if (!strcmp(fieldName, "windowY")) *out = naNum(gea->getWindowY()); - else if (!strcmp(fieldName, "time")) *out = naNum(gea->getTime()); - else if (!strcmp(fieldName, "button")) *out = naNum(gea->getButton()); - else { - return 0; + sc::CanvasPtr canvas; + if( canvas_mgr.getPropertyRoot() == props.getParent() ) + { + // get a canvas specified by its root node + canvas = canvas_mgr.getCanvas( props.getIndex() ); + if( !canvas || canvas->getProps() != &props ) + return naNil(); } - - return ""; -} - -static const char* elementGhostGetMember(naContext c, void* g, naRef field, naRef* out) -{ - const char* fieldName = naStr_data(field); - simgear::canvas::Element* e = (simgear::canvas::Element*) g; - SG_UNUSED(e); - - if (!strcmp(fieldName, "parents")) { - *out = naNewVector(c); - naVec_append(*out, elementPrototype); - } else { - return 0; + else + { + // get a canvas by name + if( props.hasValue("name") ) + canvas = canvas_mgr.getCanvas( props.getStringValue("name") ); + else if( props.hasValue("index") ) + canvas = canvas_mgr.getCanvas( props.getIntValue("index") ); } - - return ""; -} -static void elementGhostSetMember(naContext c, void* g, naRef field, naRef value) -{ - const char* fieldName = naStr_data(field); - simgear::canvas::Element* e = (simgear::canvas::Element*) g; - SG_UNUSED(fieldName); - SG_UNUSED(e); + return NasalCanvas::create(c, canvas); } - -static naRef f_canvas_getElement(naContext c, naRef me, int argc, naRef* args) +naRef f_canvasCreateGroup(sc::Canvas& canvas, const nasal::CallContext& ctx) { -// simgear::canvas::Canvas* cvs = canvasGhost(me); -// if (!cvs) { -// naRuntimeError(c, "canvas.getElement called on non-canvas object"); -// } - - return naNil(); + return NasalGroup::create + ( + ctx.c, + canvas.createGroup( ctx.getArg(0) ) + ); } -static naRef f_element_addButtonCallback(naContext c, naRef me, int argc, naRef* args) +/** + * Get group containing all gui windows + */ +naRef f_getDesktop(naContext c, naRef me, int argc, naRef* args) { - simgear::canvas::Element* e = elementGhost(me); - if (!e) { - naRuntimeError(c, "element.addButtonCallback called on non-canvas-element object"); - } - - return naNil(); + return NasalGroup::create(c, requireGUIMgr(c).getDesktop()); } -static naRef f_element_addDragCallback(naContext c, naRef me, int argc, naRef* args) +naRef f_groupCreateChild(sc::Group& group, const nasal::CallContext& ctx) { - simgear::canvas::Element* e = elementGhost(me); - if (!e) { - naRuntimeError(c, "element.addDragCallback called on non-canvas-element object"); - } - - return naNil(); + return NasalElement::create + ( + ctx.c, + group.createChild( ctx.requireArg(0), + ctx.getArg(1) ) + ); } -static naRef f_element_addMoveCallback(naContext c, naRef me, int argc, naRef* args) +naRef f_groupGetChild(sc::Group& group, const nasal::CallContext& ctx) { - simgear::canvas::Element* e = elementGhost(me); - if (!e) { - naRuntimeError(c, "element.addMoveCallback called on non-canvas-element object"); - } - - return naNil(); + return NasalElement::create + ( + ctx.c, + group.getChild( ctx.requireArg(0) ) + ); } -static naRef f_element_addScrollCallback(naContext c, naRef me, int argc, naRef* args) +naRef f_groupGetElementById(sc::Group& group, const nasal::CallContext& ctx) { - simgear::canvas::Element* e = elementGhost(me); - if (!e) { - naRuntimeError(c, "element.addScrollCallback called on non-canvas-element object"); - } - - return naNil(); + return NasalElement::create + ( + ctx.c, + group.getElementById( ctx.requireArg(0) ) + ); } -static naRef f_createCanvas(naContext c, naRef me, int argc, naRef* args) +template +naRef f_eventGetModifier(naContext, sc::MouseEvent& event) { - std::cout << "f_createCanvas" << std::endl; - - CanvasMgr* canvas_mgr = - static_cast(globals->get_subsystem("Canvas")); - if( !canvas_mgr ) - return naNil(); - - return NasalCanvas::create(c, canvas_mgr->createCanvas()); + return naNum((event.getModifiers() & Mask) != 0); } -static naRef f_setCanvasPrototype(naContext c, naRef me, int argc, naRef* args) +naRef to_nasal_helper(naContext c, const sc::ElementWeakPtr& el) { - if( argc != 1 || !naIsHash(args[0]) ) - naRuntimeError(c, "Invalid argument(s)"); - - NasalCanvas::getSingletonPtr()->addNasalBase(args[0]); - - return naNil(); + return NasalElement::create(c, el.lock()); } -naRef initNasalCanvas(naRef globals, naContext c, naRef gcSave) +naRef initNasalCanvas(naRef globals, naContext c) { - naRef props_module = naHash_cget(globals, (char*)"props"); - if( naIsNil(props_module) ) - std::cerr << "No props module" << std::endl; - - propsNodePrototype = naHash_cget(props_module, (char*)"Node"); - if( naIsNil(propsNodePrototype) ) - std::cerr << "Failed to get props.Node" << std::endl; - - /*naNewHash(c); - hashset(c, gcSave, "canvasProto", canvasPrototype); - - hashset(c, canvasPrototype, "getElement", naNewFunc(c, naNewCCode(c, f_canvas_getElement)));*/ - // set any event methods - - elementPrototype = naNewHash(c); - hashset(c, gcSave, "elementProto", elementPrototype); + using osgGA::GUIEventAdapter; + NasalEvent::init("canvas.Event") + .member("type", &sc::Event::getTypeString) + .member("target", &sc::Event::getTarget) + .member("currentTarget", &sc::Event::getCurrentTarget) + .method("stopPropagation", &sc::Event::stopPropagation); + NasalMouseEvent::init("canvas.MouseEvent") + .bases() + .member("screenX", &sc::MouseEvent::getScreenX) + .member("screenY", &sc::MouseEvent::getScreenY) + .member("clientX", &sc::MouseEvent::getClientX) + .member("clientY", &sc::MouseEvent::getClientY) + .member("localX", &sc::MouseEvent::getLocalX) + .member("localY", &sc::MouseEvent::getLocalY) + .member("deltaX", &sc::MouseEvent::getDeltaX) + .member("deltaY", &sc::MouseEvent::getDeltaY) + .member("button", &sc::MouseEvent::getButton) + .member("buttons", &sc::MouseEvent::getButtonMask) + .member("modifiers", &sc::MouseEvent::getModifiers) + .member("ctrlKey", &f_eventGetModifier) + .member("shiftKey", &f_eventGetModifier) + .member("altKey", &f_eventGetModifier) + .member("metaKey", &f_eventGetModifier) + .member("click_count", &sc::MouseEvent::getCurrentClickCount); + NasalCanvas::init("Canvas") + .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); + NasalElement::init("canvas.Element") + .member("_node_ghost", &elementGetNode) + .method("_getParent", &sc::Element::getParent) + .method("addEventListener", &sc::Element::addEventListener) + .method("getBoundingBox", &sc::Element::getBoundingBox) + .method("getTightBoundingBox", &sc::Element::getTightBoundingBox); + NasalGroup::init("canvas.Group") + .bases() + .method("_createChild", &f_groupCreateChild) + .method("_getChild", &f_groupGetChild) + .method("_getElementById", &f_groupGetElementById); + NasalText::init("canvas.Text") + .bases() + .method("getNearestCursor", &sc::Text::getNearestCursor); + + NasalWindow::init("canvas.Window") + .bases() + .member("_node_ghost", &elementGetNode) + .method("_getCanvasDecoration", &canvas::Window::getCanvasDecoration); - hashset(c, elementPrototype, "addButtonCallback", naNewFunc(c, naNewCCode(c, f_element_addButtonCallback))); - hashset(c, elementPrototype, "addDragCallback", naNewFunc(c, naNewCCode(c, f_element_addDragCallback))); - hashset(c, elementPrototype, "addMoveCallback", naNewFunc(c, naNewCCode(c, f_element_addMoveCallback))); - hashset(c, elementPrototype, "addScrollCallback", naNewFunc(c, naNewCCode(c, f_element_addScrollCallback))); - - Hash globals_module(globals, c), - canvas_module = globals_module.createHash("canvas"); - - canvas_module.set("_new", f_createCanvas); - canvas_module.set("_setPrototype", f_setCanvasPrototype); - canvas_module.set("testClass", nasal::class_::f_create); + nasal::Hash globals_module(globals, c), + canvas_module = globals_module.createHash("canvas"); - initCanvas(); + canvas_module.set("_newCanvasGhost", f_createCanvas); + canvas_module.set("_newWindowGhost", f_createWindow); + canvas_module.set("_getCanvasGhost", f_getCanvas); + canvas_module.set("_getDesktopGhost", f_getDesktop); return naNil(); }