219 lines
5.4 KiB
C++
219 lines
5.4 KiB
C++
// This file is part of VSTGUI. It is subject to the license terms
|
|
// in the LICENSE file found in the top-level directory of this
|
|
// distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
|
|
|
|
#pragma once
|
|
|
|
#include "../tiny-js/TinyJS.h"
|
|
|
|
//------------------------------------------------------------------------
|
|
namespace VSTGUI {
|
|
namespace ScriptingInternal {
|
|
|
|
//------------------------------------------------------------------------
|
|
struct ScriptAddChildScoped
|
|
{
|
|
using CScriptVar = TJS::CScriptVar;
|
|
using CScriptVarLink = TJS::CScriptVarLink;
|
|
|
|
ScriptAddChildScoped (CScriptVar& var, std::string_view name, CScriptVar* obj) : var (var)
|
|
{
|
|
if ((link = var.findChild (name)))
|
|
{
|
|
oldVar = TJS::owning (link->getVar ());
|
|
link->setVar (obj);
|
|
}
|
|
else
|
|
{
|
|
link = var.addChild (name, obj);
|
|
}
|
|
}
|
|
~ScriptAddChildScoped () noexcept
|
|
{
|
|
if (oldVar && link)
|
|
{
|
|
link->setVar (oldVar);
|
|
oldVar->release ();
|
|
}
|
|
else if (link)
|
|
{
|
|
var.removeLink (link);
|
|
}
|
|
}
|
|
|
|
private:
|
|
CScriptVar& var;
|
|
CScriptVarLink* link {nullptr};
|
|
CScriptVar* oldVar {nullptr};
|
|
};
|
|
|
|
//------------------------------------------------------------------------
|
|
inline TJS::CScriptVar* createJSFunction (TJS::JSCallback&& proc)
|
|
{
|
|
auto funcVar = new TJS::CScriptVar (TJS::TINYJS_BLANK_DATA,
|
|
TJS::SCRIPTVAR_FUNCTION | TJS::SCRIPTVAR_NATIVE);
|
|
funcVar->setCallback (std::move (proc));
|
|
return funcVar;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
inline TJS::CScriptVar* createJSFunction (TJS::JSCallback&& proc,
|
|
const std::initializer_list<std::string_view>& argNames)
|
|
{
|
|
auto f = createJSFunction (std::move (proc));
|
|
for (auto name : argNames)
|
|
f->addChildNoDup (name);
|
|
return f;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
inline TJS::CScriptVar* getArgument (TJS::CScriptVar* var, std::string_view argName,
|
|
std::string_view funcSignature)
|
|
{
|
|
auto child = var->findChild (argName);
|
|
auto result = child ? child->getVar () : nullptr;
|
|
if (!result || result->isUndefined ())
|
|
{
|
|
TJS::string s ("Missing `");
|
|
s.append (argName);
|
|
s.append ("` argument in ");
|
|
s.append (funcSignature);
|
|
throw TJS::CScriptException (std::move (s));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
inline TJS::CScriptVar* getOptionalArgument (TJS::CScriptVar* var, std::string_view argName)
|
|
{
|
|
if (auto child = var->findChild (argName))
|
|
return child->getVar ();
|
|
return nullptr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
struct ScriptObject
|
|
{
|
|
using CScriptVar = TJS::CScriptVar;
|
|
|
|
ScriptObject () { scriptVar = TJS::owning (new CScriptVar ()); }
|
|
ScriptObject (CScriptVar* var) : scriptVar (TJS::owning (var)) {}
|
|
ScriptObject (ScriptObject&& o) { *this = std::move (o); }
|
|
ScriptObject& operator= (ScriptObject&& o)
|
|
{
|
|
if (scriptVar)
|
|
scriptVar->release ();
|
|
scriptVar = nullptr;
|
|
std::swap (scriptVar, o.scriptVar);
|
|
return *this;
|
|
}
|
|
virtual ~ScriptObject () noexcept
|
|
{
|
|
if (scriptVar)
|
|
{
|
|
scriptVar->release ();
|
|
}
|
|
}
|
|
|
|
operator CScriptVar* () const
|
|
{
|
|
validate ();
|
|
return scriptVar;
|
|
}
|
|
CScriptVar* operator->() const
|
|
{
|
|
validate ();
|
|
return scriptVar;
|
|
}
|
|
|
|
CScriptVar* getVar () const
|
|
{
|
|
validate ();
|
|
return scriptVar;
|
|
}
|
|
CScriptVar* take ()
|
|
{
|
|
auto v = scriptVar;
|
|
scriptVar = nullptr;
|
|
return v;
|
|
}
|
|
void addChild (std::string_view name, ScriptObject&& obj)
|
|
{
|
|
validate ();
|
|
scriptVar->addChild (name, obj);
|
|
}
|
|
void addChild (std::string_view name, double d)
|
|
{
|
|
validate ();
|
|
scriptVar->addChild (name, new CScriptVar (d));
|
|
}
|
|
void addChild (std::string_view name, int64_t i)
|
|
{
|
|
validate ();
|
|
scriptVar->addChild (name, new CScriptVar (i));
|
|
}
|
|
void addChild (std::string_view name, int32_t i)
|
|
{
|
|
validate ();
|
|
scriptVar->addChild (name, new CScriptVar (static_cast<int64_t> (i)));
|
|
}
|
|
void addChild (std::string_view name, std::string_view value)
|
|
{
|
|
validate ();
|
|
scriptVar->addChild (name, new CScriptVar (TJS::string {value.data (), value.size ()}));
|
|
}
|
|
void addFunc (std::string_view name, std::function<void (CScriptVar*)>&& func)
|
|
{
|
|
validate ();
|
|
scriptVar->addChild (name, createJSFunction (std::move (func)));
|
|
}
|
|
void addFunc (std::string_view name, std::function<void (CScriptVar*)>&& func,
|
|
const std::initializer_list<std::string_view>& argNames)
|
|
{
|
|
validate ();
|
|
scriptVar->addChild (name, createJSFunction (std::move (func), argNames));
|
|
}
|
|
void addFunc (std::string_view name, std::string_view code)
|
|
{
|
|
validate ();
|
|
auto funcVar = new TJS::CScriptVar (TJS::TINYJS_BLANK_DATA, TJS::SCRIPTVAR_FUNCTION);
|
|
funcVar->setFunctionScript (code);
|
|
scriptVar->addChild (name, funcVar);
|
|
}
|
|
|
|
using OnDestroyFunc = std::function<void (CScriptVar*)>;
|
|
void setOnDestroy (OnDestroyFunc&& f)
|
|
{
|
|
validate ();
|
|
scriptVar->setLifeTimeObserver (OnDestroy::make (std::move (f)));
|
|
}
|
|
|
|
protected:
|
|
struct OnDestroy : TJS::IScriptVarLifeTimeObserver
|
|
{
|
|
static OnDestroy* make (OnDestroyFunc f) { return new OnDestroy (std::move (f)); }
|
|
|
|
private:
|
|
OnDestroy (OnDestroyFunc f) : func (std::move (f)) {}
|
|
|
|
void onDestroy (CScriptVar* var)
|
|
{
|
|
func (var);
|
|
delete this;
|
|
}
|
|
OnDestroyFunc func;
|
|
};
|
|
|
|
void validate () const
|
|
{
|
|
if (scriptVar == nullptr)
|
|
scriptVar = TJS::owning (new CScriptVar ());
|
|
}
|
|
|
|
mutable CScriptVar* scriptVar {nullptr};
|
|
};
|
|
|
|
//------------------------------------------------------------------------
|
|
} // ScriptingInternal
|
|
} // VSTGUI
|