X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FScripting%2FNasalCanvas.cxx;h=4fa7652652561e4714607fc18e3ea90482922ee4;hb=43add4f820300833024366cb58cfedb90bfbe5a0;hp=caa57f0779b6205aea6c95054ccacb5c961378b0;hpb=36f7ef93aa4a08a2bb37d04cb1fac0424105e895;p=flightgear.git diff --git a/src/Scripting/NasalCanvas.cxx b/src/Scripting/NasalCanvas.cxx index caa57f077..4fa765265 100644 --- a/src/Scripting/NasalCanvas.cxx +++ b/src/Scripting/NasalCanvas.cxx @@ -25,7 +25,6 @@ #include "NasalCanvas.hxx" #include #include -#include #include
#include @@ -34,9 +33,14 @@ #include #include +#include #include #include -#include +#include +#include +#include +#include +#include #include #include @@ -48,18 +52,43 @@ extern naRef propNodeGhostCreate(naContext c, SGPropertyNode* n); namespace sc = simgear::canvas; template -naRef elementGetNode(naContext c, Element& element) +naRef elementGetNode(Element& element, naContext c) { return propNodeGhostCreate(c, element.getProps()); } typedef nasal::Ghost NasalEvent; +typedef nasal::Ghost NasalCustomEvent; +typedef nasal::Ghost NasalDeviceEvent; +typedef nasal::Ghost NasalKeyboardEvent; typedef nasal::Ghost NasalMouseEvent; + +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; typedef nasal::Ghost NasalText; -typedef nasal::Ghost NasalWindow; + +typedef nasal::Ghost NasalLayoutItem; +typedef nasal::Ghost NasalLayout; +typedef nasal::Ghost NasalBoxLayout; + +typedef nasal::Ghost NasalWindow; + +naRef to_nasal_helper(naContext c, const osg::BoundingBox& bb) +{ + 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(); + + return nasal::to_nasal(c, bb_vec); +} SGPropertyNode* from_nasal_helper(naContext c, naRef ref, SGPropertyNode**) { @@ -95,7 +124,7 @@ GUIMgr& requireGUIMgr(naContext c) */ static naRef f_createCanvas(const nasal::CallContext& ctx) { - return NasalCanvas::create(ctx.c, requireCanvasMgr(ctx.c).createCanvas()); + return ctx.to_nasal(requireCanvasMgr(ctx.c).createCanvas()); } /** @@ -103,7 +132,7 @@ static naRef f_createCanvas(const nasal::CallContext& ctx) */ static naRef f_createWindow(const nasal::CallContext& ctx) { - return NasalWindow::create + return nasal::to_nasal ( ctx.c, requireGUIMgr(ctx.c).createWindow( ctx.getArg(0) ) @@ -113,11 +142,10 @@ static naRef f_createWindow(const nasal::CallContext& ctx) /** * Get ghost for existing Canvas. */ -static naRef f_getCanvas(naContext c, naRef me, int argc, naRef* args) +static naRef f_getCanvas(const nasal::CallContext& ctx) { - nasal::CallContext ctx(c, argc, args); SGPropertyNode& props = *ctx.requireArg(0); - CanvasMgr& canvas_mgr = requireCanvasMgr(c); + CanvasMgr& canvas_mgr = requireCanvasMgr(ctx.c); sc::CanvasPtr canvas; if( canvas_mgr.getPropertyRoot() == props.getParent() ) @@ -136,16 +164,12 @@ static naRef f_getCanvas(naContext c, naRef me, int argc, naRef* args) canvas = canvas_mgr.getCanvas( props.getIntValue("index") ); } - return NasalCanvas::create(c, canvas); + return ctx.to_nasal(canvas); } naRef f_canvasCreateGroup(sc::Canvas& canvas, const nasal::CallContext& ctx) { - return NasalGroup::create - ( - ctx.c, - canvas.createGroup( ctx.getArg(0) ) - ); + return ctx.to_nasal( canvas.createGroup(ctx.getArg(0)) ); } /** @@ -153,71 +177,275 @@ naRef f_canvasCreateGroup(sc::Canvas& canvas, const nasal::CallContext& ctx) */ naRef f_getDesktop(naContext c, naRef me, int argc, naRef* args) { - return NasalGroup::create(c, requireGUIMgr(c).getDesktop()); + return nasal::to_nasal(c, requireGUIMgr(c).getDesktop()); } -naRef f_elementGetTransformedBounds(sc::Element& el, const nasal::CallContext& ctx) +naRef f_setInputFocus(const nasal::CallContext& ctx) { - osg::BoundingBox bb = el.getTransformedBounds(el.getMatrix()); + requireGUIMgr(ctx.c).setInputFocus(ctx.requireArg(0)); + return naNil(); +} - 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 f_grabPointer(const nasal::CallContext& ctx) +{ + return ctx.to_nasal( + requireGUIMgr(ctx.c).grabPointer(ctx.requireArg(0)) + ); +} + +naRef f_ungrabPointer(const nasal::CallContext& ctx) +{ + requireGUIMgr(ctx.c).ungrabPointer(ctx.requireArg(0)); + return naNil(); +} - return nasal::to_nasal(ctx.c, bb_vec); +static naRef f_groupCreateChild(sc::Group& group, const nasal::CallContext& ctx) +{ + return ctx.to_nasal( group.createChild( ctx.requireArg(0), + ctx.getArg(1) ) ); } -naRef f_groupCreateChild(sc::Group& group, const nasal::CallContext& ctx) +static sc::ElementPtr f_groupGetChild(sc::Group& group, SGPropertyNode* node) { - return NasalElement::create - ( - ctx.c, - group.createChild( ctx.requireArg(0), - ctx.getArg(1) ) - ); + return group.getChild(node); } -naRef f_groupGetChild(sc::Group& group, const nasal::CallContext& ctx) +static void propElementSetData( simgear::PropertyBasedElement& el, + const std::string& name, + naContext c, + naRef ref ) { - return NasalElement::create - ( - ctx.c, - group.getChild( ctx.requireArg(0) ) + 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(); +} + +static naRef f_createCustomEvent(const nasal::CallContext& ctx) +{ + std::string const& type = ctx.requireArg(0); + if( type.empty() ) + return naNil(); + + bool bubbles = false; + 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); + bubbles = cfg.get("bubbles"); + } + + return ctx.to_nasal( + sc::CustomEventPtr(new sc::CustomEvent(type, bubbles, detail)) ); } -naRef f_groupGetElementById(sc::Group& group, const nasal::CallContext& ctx) +struct CustomEventDetailWrapper: + public SGReferenced { - return NasalElement::create - ( - ctx.c, - group.getElementById( ctx.requireArg(0) ) + sc::CustomEventPtr _event; + + CustomEventDetailWrapper(const sc::CustomEventPtr& event): + _event(event) + { + + } + + bool _get( const std::string& key, + std::string& value_out ) const + { + if( !_event ) + return false; + + simgear::StringMap::const_iterator it = _event->detail.find(key); + if( it == _event->detail.end() ) + return false; + + value_out = it->second; + return true; + } + + bool _set( const std::string& key, + const std::string& value ) + { + if( !_event ) + return false; + + _event->detail[ key ] = value; + return true; + } +}; + +static naRef f_customEventGetDetail( sc::CustomEvent& event, + naContext c ) +{ + return nasal::to_nasal( + c, + CustomEventDetailPtr(new CustomEventDetailWrapper(&event)) ); } -template -naRef f_eventGetModifier(naContext, sc::MouseEvent& event) +static naRef f_boxLayoutAddItem( sc::BoxLayout& box, + const nasal::CallContext& ctx ) +{ + box.addItem( ctx.requireArg(0), + ctx.getArg(1), + ctx.getArg(2, sc::AlignFill) ); + return naNil(); +} +static naRef f_boxLayoutInsertItem( sc::BoxLayout& box, + const nasal::CallContext& ctx ) +{ + box.insertItem( ctx.requireArg(0), + ctx.requireArg(1), + ctx.getArg(2), + ctx.getArg(3, sc::AlignFill) ); + return naNil(); +} + +static naRef f_boxLayoutAddStretch( sc::BoxLayout& box, + const nasal::CallContext& ctx ) { - return naNum((event.getButtonMask() & Mask) != 0); + box.addStretch( ctx.getArg(0) ); + return naNil(); +} +static naRef f_boxLayoutInsertStretch( sc::BoxLayout& box, + const nasal::CallContext& ctx ) +{ + box.insertStretch( ctx.requireArg(0), + ctx.getArg(1) ); + return naNil(); } -naRef to_nasal_helper(naContext c, const sc::ElementWeakPtr& el) +template +static naRef f_newAsBase(const nasal::CallContext& ctx) { - return NasalElement::create(c, el.lock()); + return ctx.to_nasal(new Type()); } naRef initNasalCanvas(naRef globals, naContext c) { + nasal::Hash globals_module(globals, c), + canvas_module = globals_module.createHash("canvas"); + + nasal::Object::setupGhost(); + + //---------------------------------------------------------------------------- + // Events + 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") + .member("defaultPrevented", &sc::Event::defaultPrevented) + .method("stopPropagation", &sc::Event::stopPropagation) + .method("preventDefault", &sc::Event::preventDefault); + + NasalCustomEvent::init("canvas.CustomEvent") + .bases() + .member("detail", &f_customEventGetDetail, &sc::CustomEvent::setDetail); + NasalCustomEventDetail::init("canvas.CustomEventDetail") + ._get(&CustomEventDetailWrapper::_get) + ._set(&CustomEventDetailWrapper::_set); + + canvas_module.createHash("CustomEvent") + .set("new", &f_createCustomEvent); + + NasalDeviceEvent::init("canvas.DeviceEvent") .bases() + .member("modifiers", &sc::DeviceEvent::getModifiers) + .member("ctrlKey", &sc::DeviceEvent::ctrlKey) + .member("shiftKey", &sc::DeviceEvent::shiftKey) + .member("altKey", &sc::DeviceEvent::altKey) + .member("metaKey", &sc::DeviceEvent::metaKey); + + NasalKeyboardEvent::init("canvas.KeyboardEvent") + .bases() + .member("key", &sc::KeyboardEvent::key) + .member("location", &sc::KeyboardEvent::location) + .member("repeat", &sc::KeyboardEvent::repeat) + .member("charCode", &sc::KeyboardEvent::charCode) + .member("keyCode", &sc::KeyboardEvent::keyCode); + + NasalMouseEvent::init("canvas.MouseEvent") + .bases() .member("screenX", &sc::MouseEvent::getScreenX) .member("screenY", &sc::MouseEvent::getScreenY) .member("clientX", &sc::MouseEvent::getClientX) @@ -228,45 +456,135 @@ naRef initNasalCanvas(naRef globals, naContext c) .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); + + //---------------------------------------------------------------------------- + // Canvas & elements + + NasalPropertyBasedElement::init("PropertyBasedElement") + .method("data", &f_propElementData); NasalCanvas::init("Canvas") + .bases() + .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", + static_cast + (&sc::Canvas::addEventListener) ) + .method("dispatchEvent", &sc::Canvas::dispatchEvent) + .method("setLayout", &sc::Canvas::setLayout) + .method("setFocusElement", &sc::Canvas::setFocusElement) + .method("clearFocusElement", &sc::Canvas::clearFocusElement); + + canvas_module.set("_newCanvasGhost", f_createCanvas); + canvas_module.set("_getCanvasGhost", f_getCanvas); + 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("getTransformedBounds", &f_elementGetTransformedBounds); + .method("setFocus", &sc::Element::setFocus) + .method("dispatchEvent", &sc::Element::dispatchEvent) + .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); + .method( "_getChild", &f_groupGetChild) + .method("_getElementById", &sc::Group::getElementById); NasalText::init("canvas.Text") .bases() - .method("getNearestCursor", &sc::Text::getNearestCursor); + .method("heightForWidth", &sc::Text::heightForWidth) + .method("maxWidth", &sc::Text::maxWidth) + .method("lineCount", &sc::Text::lineCount) + .method("lineLength", &sc::Text::lineLength) + .method("getNearestCursor", &sc::Text::getNearestCursor) + .method("getCursorPos", &sc::Text::getCursorPos); + + //---------------------------------------------------------------------------- + // Layouting + +#define ALIGN_ENUM_MAPPING(key, val, comment) canvas_module.set(#key, sc::key); +# include +#undef ALIGN_ENUM_MAPPING + + void (sc::LayoutItem::*f_layoutItemSetContentsMargins)(int, int, int, int) + = &sc::LayoutItem::setContentsMargins; + + NasalLayoutItem::init("canvas.LayoutItem") + .method("getCanvas", &sc::LayoutItem::getCanvas) + .method("setCanvas", &sc::LayoutItem::setCanvas) + .method("getParent", &sc::LayoutItem::getParent) + .method("setParent", &sc::LayoutItem::setParent) + .method("setContentsMargins", f_layoutItemSetContentsMargins) + .method("setContentsMargin", &sc::LayoutItem::setContentsMargin) + .method("sizeHint", &sc::LayoutItem::sizeHint) + .method("minimumSize", &sc::LayoutItem::minimumSize) + .method("maximumSize", &sc::LayoutItem::maximumSize) + .method("hasHeightForWidth", &sc::LayoutItem::hasHeightForWidth) + .method("heightForWidth", &sc::LayoutItem::heightForWidth) + .method("minimumHeightForWidth", &sc::LayoutItem::minimumHeightForWidth) + .method("setAlignment", &sc::LayoutItem::setAlignment) + .method("alignment", &sc::LayoutItem::alignment) + .method("setVisible", &sc::LayoutItem::setVisible) + .method("isVisible", &sc::LayoutItem::isVisible) + .method("isExplicitlyHidden", &sc::LayoutItem::isExplicitlyHidden) + .method("show", &sc::LayoutItem::show) + .method("hide", &sc::LayoutItem::hide) + .method("setGeometry", &sc::LayoutItem::setGeometry) + .method("geometry", &sc::LayoutItem::geometry); + sc::NasalWidget::setupGhost(canvas_module); + + NasalLayout::init("canvas.Layout") + .bases() + .method("addItem", &sc::Layout::addItem) + .method("setSpacing", &sc::Layout::setSpacing) + .method("spacing", &sc::Layout::spacing) + .method("count", &sc::Layout::count) + .method("itemAt", &sc::Layout::itemAt) + .method("takeAt", &sc::Layout::takeAt) + .method("removeItem", &sc::Layout::removeItem) + .method("clear", &sc::Layout::clear); + + NasalBoxLayout::init("canvas.BoxLayout") + .bases() + .method("addItem", &f_boxLayoutAddItem) + .method("addSpacing", &sc::BoxLayout::addSpacing) + .method("addStretch", &f_boxLayoutAddStretch) + .method("insertItem", &f_boxLayoutInsertItem) + .method("insertSpacing", &sc::BoxLayout::insertSpacing) + .method("insertStretch", &f_boxLayoutInsertStretch) + .method("setStretch", &sc::BoxLayout::setStretch) + .method("setStretchFactor", &sc::BoxLayout::setStretchFactor) + .method("stretch", &sc::BoxLayout::stretch); + + canvas_module.createHash("HBoxLayout") + .set("new", &f_newAsBase); + canvas_module.createHash("VBoxLayout") + .set("new", &f_newAsBase); + + //---------------------------------------------------------------------------- + // Window NasalWindow::init("canvas.Window") .bases() - .member("_node_ghost", &elementGetNode) - .method("_getCanvasDecoration", &canvas::Window::getCanvasDecoration); - - nasal::Hash globals_module(globals, c), - canvas_module = globals_module.createHash("canvas"); + .bases() + .member("_node_ghost", &elementGetNode) + .method("_getCanvasDecoration", &sc::Window::getCanvasDecoration) + .method("setLayout", &sc::Window::setLayout); - canvas_module.set("_newCanvasGhost", f_createCanvas); canvas_module.set("_newWindowGhost", f_createWindow); - canvas_module.set("_getCanvasGhost", f_getCanvas); canvas_module.set("_getDesktopGhost", f_getDesktop); + canvas_module.set("setInputFocus", f_setInputFocus); + canvas_module.set("grabPointer", f_grabPointer); + canvas_module.set("ungrabPointer", f_ungrabPointer); return naNil(); }