Initial release
This commit is contained in:
+134
@@ -0,0 +1,134 @@
|
||||
// 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 "scriptobject.h"
|
||||
#include "../../lib/vstguifwd.h"
|
||||
#include "../../uidescription/uidescriptionfwd.h"
|
||||
#include "../../lib/events.h"
|
||||
#include "../../lib/crect.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace ScriptingInternal {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline ScriptObject makeScriptRect (const CRect& rect)
|
||||
{
|
||||
using namespace std::literals;
|
||||
ScriptObject obj;
|
||||
obj.addChild ("left"sv, rect.left);
|
||||
obj.addChild ("top"sv, rect.top);
|
||||
obj.addChild ("right"sv, rect.right);
|
||||
obj.addChild ("bottom"sv, rect.bottom);
|
||||
obj.addFunc ("getWidth"sv, "{ return this.right - this.left; }"sv);
|
||||
obj.addFunc ("getHeight"sv, "{ return this.bottom - this.top; }"sv);
|
||||
return obj;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline ScriptObject makeScriptPoint (const CPoint& point)
|
||||
{
|
||||
using namespace std::literals;
|
||||
ScriptObject obj;
|
||||
obj.addChild ("x"sv, point.x);
|
||||
obj.addChild ("y"sv, point.y);
|
||||
return obj;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline CPoint fromScriptPoint (TJS::CScriptVar& var)
|
||||
{
|
||||
using namespace std::literals;
|
||||
CPoint result {};
|
||||
if (auto xVar = var.findChild ("x"sv))
|
||||
result.x = xVar->getVar ()->getDouble ();
|
||||
else
|
||||
throw TJS::CScriptException ("Not a point object, missing 'x' member");
|
||||
if (auto yVar = var.findChild ("y"sv))
|
||||
result.y = yVar->getVar ()->getDouble ();
|
||||
else
|
||||
throw TJS::CScriptException ("Not a point object, missing 'y' member");
|
||||
return result;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline CRect fromScriptRect (TJS::CScriptVar& var)
|
||||
{
|
||||
using namespace std::literals;
|
||||
CRect result {};
|
||||
auto leftVar = var.findChild ("left"sv);
|
||||
auto topVar = var.findChild ("top"sv);
|
||||
auto rightVar = var.findChild ("right"sv);
|
||||
auto bottomVar = var.findChild ("bottom"sv);
|
||||
if (!leftVar || !topVar || !rightVar || !bottomVar)
|
||||
throw TJS::CScriptException ("Expecting a rect object here");
|
||||
result.left = leftVar->getVar ()->getDouble ();
|
||||
result.top = topVar->getVar ()->getDouble ();
|
||||
result.right = rightVar->getVar ()->getDouble ();
|
||||
result.bottom = bottomVar->getVar ()->getDouble ();
|
||||
return result;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline ScriptObject makeScriptEvent (const Event& event)
|
||||
{
|
||||
using namespace std::literals;
|
||||
ScriptObject obj;
|
||||
if (auto modifierEvent = asModifierEvent (event))
|
||||
{
|
||||
ScriptObject mod;
|
||||
if (modifierEvent->modifiers.has (ModifierKey::Shift))
|
||||
mod.addChild ("shift"sv, true);
|
||||
if (modifierEvent->modifiers.has (ModifierKey::Alt))
|
||||
mod.addChild ("alt"sv, true);
|
||||
if (modifierEvent->modifiers.has (ModifierKey::Control))
|
||||
mod.addChild ("control"sv, true);
|
||||
if (modifierEvent->modifiers.has (ModifierKey::Super))
|
||||
mod.addChild ("super"sv, true);
|
||||
obj.addChild ("modifiers"sv, std::move (mod));
|
||||
}
|
||||
if (auto mouseEvent = asMousePositionEvent (event))
|
||||
{
|
||||
obj.addChild ("mousePosition"sv, makeScriptPoint (mouseEvent->mousePosition));
|
||||
}
|
||||
if (auto mouseEvent = asMouseEvent (event))
|
||||
{
|
||||
ScriptObject buttons;
|
||||
if (mouseEvent->buttonState.has (MouseButton::Left))
|
||||
buttons.addChild ("left"sv, true);
|
||||
if (mouseEvent->buttonState.has (MouseButton::Right))
|
||||
buttons.addChild ("right"sv, true);
|
||||
if (mouseEvent->buttonState.has (MouseButton::Middle))
|
||||
buttons.addChild ("middle"sv, true);
|
||||
obj.addChild ("mouseButtons"sv, std::move (buttons));
|
||||
}
|
||||
if (event.type == EventType::MouseWheel)
|
||||
{
|
||||
const auto& wheelEvent = castMouseWheelEvent (event);
|
||||
ScriptObject wheel;
|
||||
wheel.addChild ("deltaX"sv, wheelEvent.deltaX);
|
||||
wheel.addChild ("deltaY"sv, wheelEvent.deltaY);
|
||||
if (wheelEvent.flags & MouseWheelEvent::Flags::DirectionInvertedFromDevice)
|
||||
wheel.addChild ("directionInvertedFromDevice"sv, true);
|
||||
if (wheelEvent.flags & MouseWheelEvent::Flags::PreciseDeltas)
|
||||
wheel.addChild ("preciceDelta"sv, true);
|
||||
obj.addChild ("mouseWheel"sv, std::move (wheel));
|
||||
}
|
||||
if (auto keyEvent = asKeyboardEvent (event))
|
||||
{
|
||||
ScriptObject key;
|
||||
key.addChild ("character"sv, static_cast<int> (keyEvent->character));
|
||||
key.addChild ("virtual"sv, static_cast<int> (keyEvent->virt));
|
||||
key.addChild ("isRepeat"sv, keyEvent->isRepeat);
|
||||
obj.addChild ("key"sv, std::move (key));
|
||||
}
|
||||
obj.addChild ("consume"sv, 0);
|
||||
return obj;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // ScriptingInternal
|
||||
} // VSTGUI
|
||||
+214
@@ -0,0 +1,214 @@
|
||||
// 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
|
||||
|
||||
#include "drawable.h"
|
||||
#include "converters.h"
|
||||
#include "../../lib/cframe.h"
|
||||
#include "../../lib/cdrawcontext.h"
|
||||
#include "../../lib/cgraphicspath.h"
|
||||
#include "../../lib/cgraphicstransform.h"
|
||||
#include "../../uidescription/detail/uiviewcreatorattributes.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace ScriptingInternal {
|
||||
using namespace std::literals;
|
||||
using namespace TJS;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
void JavaScriptDrawable::onDraw (CDrawContext* context, const CRect& rect, const CRect& viewSize)
|
||||
{
|
||||
if (!scriptObject)
|
||||
{
|
||||
auto dashLength = std::round ((viewSize.getWidth () * 2 + viewSize.getHeight () * 2) / 40.);
|
||||
CLineStyle ls (CLineStyle::kLineCapButt, CLineStyle::kLineJoinMiter, 0,
|
||||
{dashLength, dashLength});
|
||||
|
||||
auto lineWidth = 1.;
|
||||
auto size = viewSize;
|
||||
size.inset (lineWidth / 2., lineWidth / 2.);
|
||||
context->setLineStyle (ls);
|
||||
context->setLineWidth (lineWidth);
|
||||
context->setFrameColor (kBlackCColor);
|
||||
context->drawRect (size, kDrawStroked);
|
||||
|
||||
ls.setDashPhase (dashLength * lineWidth);
|
||||
context->setLineStyle (ls);
|
||||
context->setFrameColor (kWhiteCColor);
|
||||
context->drawRect (size, kDrawStroked);
|
||||
return;
|
||||
}
|
||||
auto scriptContext = scriptObject->getContext ();
|
||||
if (!scriptContext)
|
||||
return;
|
||||
context->saveGlobalState ();
|
||||
|
||||
drawContext.setDrawContext (context, scriptContext->getUIDescription ());
|
||||
|
||||
CDrawContext::Transform tm (*context, CGraphicsTransform ().translate (viewSize.getTopLeft ()));
|
||||
|
||||
auto rectVar = makeScriptRect (rect);
|
||||
auto scriptRoot = scriptContext->getRoot ();
|
||||
ScriptAddChildScoped scs (*scriptRoot, "view"sv, *scriptObject);
|
||||
ScriptAddChildScoped scs2 (*scriptRoot, "context"sv, drawContext);
|
||||
ScriptAddChildScoped scs3 (*scriptRoot, "rect"sv, rectVar);
|
||||
scriptContext->evalScript ("view.draw(context, rect);"sv);
|
||||
|
||||
drawContext.setDrawContext (nullptr, nullptr);
|
||||
|
||||
context->restoreGlobalState ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void JavaScriptDrawable::setup (ViewScriptObject* inObject) { scriptObject = inObject; }
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool JavaScriptDrawable::onDrawFocusOnTop ()
|
||||
{
|
||||
auto scriptContext = scriptObject->getContext ();
|
||||
if (!scriptContext)
|
||||
return false;
|
||||
|
||||
if (scriptObject->getVar ()->findChild ("drawFocusOnTop"sv) == nullptr)
|
||||
return false;
|
||||
|
||||
auto scriptRoot = scriptContext->getRoot ();
|
||||
ScriptAddChildScoped scs (*scriptRoot, "view"sv, *scriptObject);
|
||||
auto boolResult = scriptContext->evalScript ("view.drawFocusOnTop();"sv);
|
||||
return boolResult->isNumeric () ? boolResult->getInt () : false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool JavaScriptDrawable::onGetFocusPath (CGraphicsPath& outPath, CCoord focusWidth,
|
||||
const CRect& viewSize)
|
||||
{
|
||||
if (auto scriptContext = scriptObject->getContext ())
|
||||
{
|
||||
if (scriptObject->getVar ()->findChild ("getFocusPath"sv) == nullptr)
|
||||
{
|
||||
auto r = viewSize;
|
||||
outPath.addRect (r);
|
||||
r.extend (focusWidth, focusWidth);
|
||||
outPath.addRect (r);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto scriptRoot = scriptContext->getRoot ();
|
||||
auto path = makeOwned<CGraphicsPath> (outPath);
|
||||
ScriptObject focusWidthVar;
|
||||
focusWidthVar->setDouble (focusWidth);
|
||||
ScriptAddChildScoped scs (*scriptRoot, "view"sv, *scriptObject);
|
||||
ScriptAddChildScoped scs2 (*scriptRoot, "path"sv, makeGraphicsPathScriptObject (path));
|
||||
ScriptAddChildScoped scs3 (*scriptRoot, "focusWidth"sv, focusWidthVar);
|
||||
auto boolResult = scriptContext->evalScript ("view.getFocusPath(path, focusWidth);"sv);
|
||||
if (boolResult->isNumeric ())
|
||||
{
|
||||
if (boolResult->getInt () == 1)
|
||||
{
|
||||
CGraphicsTransform tm;
|
||||
tm.translate (viewSize.left, viewSize.top);
|
||||
outPath.addPath (*path, &tm);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
void JavaScriptDrawableView::drawRect (CDrawContext* context, const CRect& rect)
|
||||
{
|
||||
onDraw (context, rect, getViewSize ());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool JavaScriptDrawableView::drawFocusOnTop ()
|
||||
{
|
||||
if (wantsFocus ())
|
||||
return onDrawFocusOnTop ();
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool JavaScriptDrawableView::getFocusPath (CGraphicsPath& outPath)
|
||||
{
|
||||
if (wantsFocus ())
|
||||
return onGetFocusPath (outPath, getFrame ()->getFocusWidth (), getViewSize ());
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
void JavaScriptDrawableControl::draw (CDrawContext* context) { drawRect (context, getViewSize ()); }
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void JavaScriptDrawableControl::drawRect (CDrawContext* context, const CRect& rect)
|
||||
{
|
||||
onDraw (context, rect, getViewSize ());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool JavaScriptDrawableControl::drawFocusOnTop ()
|
||||
{
|
||||
if (wantsFocus ())
|
||||
return onDrawFocusOnTop ();
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool JavaScriptDrawableControl::getFocusPath (CGraphicsPath& outPath)
|
||||
{
|
||||
if (wantsFocus ())
|
||||
return onGetFocusPath (outPath, getFrame ()->getFocusWidth (), getViewSize ());
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
IdStringPtr JavaScriptDrawableViewCreator::getViewName () const { return "JavaScriptDrawableView"; }
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
IdStringPtr JavaScriptDrawableViewCreator::getBaseViewName () const
|
||||
{
|
||||
return UIViewCreator::kCView;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
CView* JavaScriptDrawableViewCreator::create (const UIAttributes& attributes,
|
||||
const IUIDescription* description) const
|
||||
{
|
||||
return new JavaScriptDrawableView (CRect ());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
IdStringPtr JavaScriptDrawableControlCreator::getViewName () const
|
||||
{
|
||||
return "JavaScriptDrawableControl";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
IdStringPtr JavaScriptDrawableControlCreator::getBaseViewName () const
|
||||
{
|
||||
return UIViewCreator::kCControl;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
CView* JavaScriptDrawableControlCreator::create (const UIAttributes& attributes,
|
||||
const IUIDescription* description) const
|
||||
{
|
||||
return new JavaScriptDrawableControl (CRect ());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // ScriptingInternal
|
||||
} // VSTGUI
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
// 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 "viewscriptobject.h"
|
||||
#include "drawcontextobject.h"
|
||||
#include "../../lib/cview.h"
|
||||
#include "../../lib/controls/ccontrol.h"
|
||||
#include "../../uidescription/iviewcreator.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace ScriptingInternal {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct JavaScriptDrawable
|
||||
{
|
||||
void onDraw (CDrawContext* context, const CRect& rect, const CRect& viewSize);
|
||||
bool onDrawFocusOnTop ();
|
||||
bool onGetFocusPath (CGraphicsPath& outPath, CCoord focusWidth, const CRect& viewSize);
|
||||
|
||||
void setup (ViewScriptObject* object);
|
||||
|
||||
private:
|
||||
ViewScriptObject* scriptObject {nullptr};
|
||||
DrawContextObject drawContext;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct JavaScriptDrawableView : CView,
|
||||
IFocusDrawing,
|
||||
JavaScriptDrawable
|
||||
{
|
||||
using CView::CView;
|
||||
|
||||
void drawRect (CDrawContext* context, const CRect& rect) override;
|
||||
bool drawFocusOnTop () override;
|
||||
bool getFocusPath (CGraphicsPath& outPath) override;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct JavaScriptDrawableControl : CControl,
|
||||
JavaScriptDrawable
|
||||
{
|
||||
using CControl::CControl;
|
||||
|
||||
void draw (CDrawContext* pContext) override;
|
||||
void drawRect (CDrawContext* context, const CRect& rect) override;
|
||||
bool drawFocusOnTop () override;
|
||||
bool getFocusPath (CGraphicsPath& outPath) override;
|
||||
|
||||
CLASS_METHODS_NOCOPY (JavaScriptDrawableControl, CControl);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct JavaScriptDrawableViewCreator : ViewCreatorAdapter
|
||||
{
|
||||
IdStringPtr getViewName () const override;
|
||||
IdStringPtr getBaseViewName () const override;
|
||||
CView* create (const UIAttributes& attributes,
|
||||
const IUIDescription* description) const override;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct JavaScriptDrawableControlCreator : ViewCreatorAdapter
|
||||
{
|
||||
IdStringPtr getViewName () const override;
|
||||
IdStringPtr getBaseViewName () const override;
|
||||
CView* create (const UIAttributes& attributes,
|
||||
const IUIDescription* description) const override;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // ScriptingInternal
|
||||
} // VSTGUI
|
||||
+870
@@ -0,0 +1,870 @@
|
||||
// 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
|
||||
|
||||
#include "drawcontextobject.h"
|
||||
#include "converters.h"
|
||||
#include "../../lib/cdrawcontext.h"
|
||||
#include "../../lib/cgraphicspath.h"
|
||||
#include "../../lib/cgradient.h"
|
||||
#include "../../uidescription/uidescription.h"
|
||||
#include "../../uidescription/uiviewcreator.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace ScriptingInternal {
|
||||
|
||||
using namespace std::literals;
|
||||
using namespace TJS;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
static T getFromVar (CScriptVar* var, const string& exceptionString)
|
||||
{
|
||||
auto customData = var->getCustomData ();
|
||||
if (!customData.has_value ())
|
||||
throw CScriptException (exceptionString);
|
||||
try
|
||||
{
|
||||
auto result = std::any_cast<T> (customData);
|
||||
return result;
|
||||
}
|
||||
catch (const std::bad_any_cast&)
|
||||
{
|
||||
throw CScriptException (exceptionString);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static SharedPointer<CGraphicsPath> getGraphicsPath (CScriptVar* var, std::string_view varName,
|
||||
std::string_view signature)
|
||||
{
|
||||
auto pathVar = getArgument (var, varName, signature);
|
||||
return getFromVar<SharedPointer<CGraphicsPath>> (pathVar, "Variable is not a graphics path");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static SharedPointer<CGradient> getGradient (CScriptVar* var, std::string_view varName,
|
||||
std::string_view signature)
|
||||
{
|
||||
auto gradientVar = getArgument (var, varName, signature);
|
||||
return getFromVar<SharedPointer<CGradient>> (gradientVar, "Variable is not a gradient");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static std::shared_ptr<CGraphicsTransform> getTransformMatrix (CScriptVar* var,
|
||||
std::string_view varName,
|
||||
std::string_view signature)
|
||||
{
|
||||
auto tmVar = getArgument (var, varName, signature);
|
||||
return getFromVar<std::shared_ptr<CGraphicsTransform>> (tmVar,
|
||||
"Variable is not a transform matrix");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static std::shared_ptr<CGraphicsTransform> getOptionalTransformMatrix (CScriptVar* var,
|
||||
std::string_view varName,
|
||||
std::string_view signature)
|
||||
{
|
||||
if (auto tmVar = getOptionalArgument (var, varName))
|
||||
return getFromVar<std::shared_ptr<CGraphicsTransform>> (
|
||||
tmVar, "Variable is not a transform matrix");
|
||||
return {};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static CRect getRect (CScriptVar* var, std::string_view varName, std::string_view signature)
|
||||
{
|
||||
auto rectVar = getArgument (var, varName, signature);
|
||||
auto rect = fromScriptRect (*rectVar);
|
||||
return rect;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static CPoint getPoint (CScriptVar* var, std::string_view varName, std::string_view signature)
|
||||
{
|
||||
auto pointVar = getArgument (var, varName, signature);
|
||||
auto point = fromScriptPoint (*pointVar);
|
||||
return point;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static CPoint getOptionalPoint (CScriptVar* var, std::string_view varName,
|
||||
std::string_view signature, CPoint defaultPoint = {})
|
||||
{
|
||||
if (auto pointVar = getOptionalArgument (var, varName))
|
||||
return fromScriptPoint (*pointVar);
|
||||
return defaultPoint;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static double getDouble (CScriptVar* var, std::string_view varName, std::string_view signature)
|
||||
{
|
||||
auto doubleVar = getArgument (var, varName, signature);
|
||||
if (!doubleVar->isNumeric ())
|
||||
{
|
||||
TJS::string s ("'");
|
||||
s.append (varName);
|
||||
s.append ("' must be a number");
|
||||
throw CScriptException (s);
|
||||
}
|
||||
return doubleVar->getDouble ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static int64_t getInt (CScriptVar* var, std::string_view varName, std::string_view signature)
|
||||
{
|
||||
auto intVar = getArgument (var, varName, signature);
|
||||
if (!intVar->isNumeric ())
|
||||
{
|
||||
TJS::string s ("'");
|
||||
s.append (varName);
|
||||
s.append ("' must be numeric");
|
||||
throw CScriptException (s);
|
||||
}
|
||||
return intVar->getInt ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static int64_t getOptionalInt (CScriptVar* var, std::string_view varName,
|
||||
std::string_view signature, int64_t defaultInt = {})
|
||||
{
|
||||
if (auto intVar = getOptionalArgument (var, varName))
|
||||
{
|
||||
if (!intVar->isNumeric ())
|
||||
{
|
||||
TJS::string s ("'");
|
||||
s.append (varName);
|
||||
s.append ("' must be numeric");
|
||||
throw CScriptException (s);
|
||||
}
|
||||
return intVar->getInt ();
|
||||
}
|
||||
return defaultInt;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static CColor getColor (CScriptVar* var, const IUIDescription* uiDesc, std::string_view varName,
|
||||
std::string_view signature)
|
||||
{
|
||||
auto colorVar = getArgument (var, varName, signature);
|
||||
auto colorStr = colorVar->getString ();
|
||||
CColor color {};
|
||||
if (!UIViewCreator::stringToColor (colorStr, color, uiDesc))
|
||||
{
|
||||
string str ("'");
|
||||
str += colorStr;
|
||||
str += "' is not a color in a call to ";
|
||||
str += signature;
|
||||
throw CScriptException (str);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct TransformMatrixScriptObject : ScriptObject
|
||||
{
|
||||
using TransformMatrixPtr = std::shared_ptr<CGraphicsTransform>;
|
||||
|
||||
TransformMatrixScriptObject (TransformMatrixPtr tm = std::make_shared<CGraphicsTransform> ())
|
||||
: ScriptObject (new CScriptVar ("", SCRIPTVAR_OBJECT))
|
||||
{
|
||||
scriptVar->setCustomData (tm);
|
||||
addFunc ("concat"sv, [tm] (auto var) { concat (tm, var); }, {"transformMatrix"sv});
|
||||
addFunc ("inverse"sv, [tm] (auto var) { inverse (tm, var); });
|
||||
addFunc ("rotate"sv, [tm] (auto var) { rotate (tm, var); }, {"angle"sv, "center?"sv});
|
||||
addFunc ("scale"sv, [tm] (auto var) { scale (tm, var); }, {"x"sv, "y"sv});
|
||||
addFunc ("skewX"sv, [tm] (auto var) { skewX (tm, var); }, {"angle"sv});
|
||||
addFunc ("skewY"sv, [tm] (auto var) { skewY (tm, var); }, {"angle"sv});
|
||||
addFunc ("translate"sv, [tm] (auto var) { translate (tm, var); }, {"x"sv, "y"sv});
|
||||
addFunc ("transform"sv, [tm] (auto var) { transform (tm, var); }, {"pointOrRect"sv});
|
||||
}
|
||||
|
||||
static void inverse (const TransformMatrixPtr& tm, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "matrix.inverse();"sv;
|
||||
auto iTm = tm->inverse ();
|
||||
TransformMatrixScriptObject obj (std::make_shared<CGraphicsTransform> (iTm));
|
||||
var->setReturnVar (obj.take ());
|
||||
}
|
||||
|
||||
static void concat (const TransformMatrixPtr& tm, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "matrix.concat(transformMatrix);"sv;
|
||||
auto other = getTransformMatrix (var, "transformMatrix"sv, signature);
|
||||
auto result = *(tm.get ()) * *(other.get ());
|
||||
*(tm.get ()) = result;
|
||||
}
|
||||
|
||||
static void translate (const TransformMatrixPtr& tm, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "matrix.translate(x, y);"sv;
|
||||
auto x = getDouble (var, "x"sv, signature);
|
||||
auto y = getDouble (var, "y"sv, signature);
|
||||
tm->translate (x, y);
|
||||
}
|
||||
|
||||
static void scale (const TransformMatrixPtr& tm, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "matrix.scale(x, y);"sv;
|
||||
auto x = getDouble (var, "x"sv, signature);
|
||||
auto y = getDouble (var, "y"sv, signature);
|
||||
tm->scale (x, y);
|
||||
}
|
||||
|
||||
static void rotate (const TransformMatrixPtr& tm, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "matrix.rotate(angle, center?);"sv;
|
||||
auto angle = getDouble (var, "angle"sv, signature);
|
||||
if (auto centerVar = getOptionalArgument (var, "center?"sv))
|
||||
{
|
||||
auto center = fromScriptPoint (*centerVar);
|
||||
tm->rotate (angle, center);
|
||||
}
|
||||
else
|
||||
{
|
||||
tm->rotate (angle);
|
||||
}
|
||||
}
|
||||
|
||||
static void skewX (const TransformMatrixPtr& tm, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "matrix.skewX(angle);"sv;
|
||||
auto angle = getDouble (var, "angle"sv, signature);
|
||||
tm->skewX (angle);
|
||||
}
|
||||
|
||||
static void skewY (const TransformMatrixPtr& tm, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "matrix.skewY(angle);"sv;
|
||||
auto angle = getDouble (var, "angle"sv, signature);
|
||||
tm->skewY (angle);
|
||||
}
|
||||
|
||||
static void transform (const TransformMatrixPtr& tm, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "matrix.transform(pointOrRect);"sv;
|
||||
auto pointOrRect = getArgument (var, "pointOrRect"sv, signature);
|
||||
auto xVar = getOptionalArgument (pointOrRect, "x"sv);
|
||||
auto yVar = getOptionalArgument (pointOrRect, "y"sv);
|
||||
if (xVar && yVar)
|
||||
{
|
||||
auto x = xVar->getDouble ();
|
||||
auto y = yVar->getDouble ();
|
||||
tm->transform (x, y);
|
||||
xVar->setDouble (x);
|
||||
yVar->setDouble (y);
|
||||
return;
|
||||
}
|
||||
auto leftVar = getOptionalArgument (pointOrRect, "left"sv);
|
||||
auto topVar = getOptionalArgument (pointOrRect, "top"sv);
|
||||
auto rightVar = getOptionalArgument (pointOrRect, "right"sv);
|
||||
auto bottomVar = getOptionalArgument (pointOrRect, "bottom"sv);
|
||||
if (leftVar && topVar && rightVar && bottomVar)
|
||||
{
|
||||
CRect r (leftVar->getDouble (), topVar->getDouble (), rightVar->getDouble (),
|
||||
bottomVar->getDouble ());
|
||||
tm->transform (r);
|
||||
leftVar->setDouble (r.left);
|
||||
topVar->setDouble (r.top);
|
||||
rightVar->setDouble (r.right);
|
||||
bottomVar->setDouble (r.bottom);
|
||||
return;
|
||||
}
|
||||
|
||||
string s ("Argument is not a point or a rect in ");
|
||||
s.append (signature);
|
||||
throw CScriptException (std::move (s));
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
TJS::CScriptVar* makeTransformMatrixObject ()
|
||||
{
|
||||
TransformMatrixScriptObject obj;
|
||||
return obj.take ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct GradientScriptObject : ScriptObject
|
||||
{
|
||||
GradientScriptObject (const SharedPointer<CGradient>& g, const IUIDescription* uiDesc)
|
||||
: ScriptObject (new CScriptVar ("", SCRIPTVAR_OBJECT))
|
||||
{
|
||||
scriptVar->setCustomData (g);
|
||||
|
||||
addFunc ("addColorStop"sv, [g, uiDesc] (auto var) { addColorStop (g, uiDesc, var); },
|
||||
{"position"sv, "color"sv});
|
||||
}
|
||||
|
||||
static void addColorStop (const SharedPointer<CGradient>& g, const IUIDescription* uiDesc,
|
||||
CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "gradient.addColorStop(position, color);"sv;
|
||||
auto position = getDouble (var, "position"sv, signature);
|
||||
auto color = getColor (var, uiDesc, "color"sv, signature);
|
||||
g->addColorStop (position, color);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct GraphicsPathScriptObject : ScriptObject
|
||||
{
|
||||
GraphicsPathScriptObject (const SharedPointer<CGraphicsPath>& p)
|
||||
: ScriptObject (new CScriptVar ("", SCRIPTVAR_OBJECT))
|
||||
{
|
||||
scriptVar->setCustomData (p);
|
||||
|
||||
addFunc ("addEllipse"sv, [p] (auto var) { addEllipse (p, var); }, {"rect"sv});
|
||||
addFunc ("addArc"sv, [p] (auto var) { addArc (p, var); },
|
||||
{"rect"sv, "startAngle"sv, "endAngle"sv, "clockwise"sv});
|
||||
addFunc ("addBezierCurve"sv, [p] (auto var) { addBezierCurve (p, var); },
|
||||
{"control1"sv, "control2"sv, "end"sv});
|
||||
addFunc ("addLine"sv, [p] (auto var) { addLine (p, var); }, {"to"sv});
|
||||
addFunc ("addPath"sv, [p] (auto var) { addPath (p, var); },
|
||||
{"path"sv, "transformMatrix?"sv});
|
||||
addFunc ("addRect"sv, [p] (auto var) { addRect (p, var); }, {"rect"sv});
|
||||
addFunc ("addRoundRect"sv, [p] (auto var) { addRoundRect (p, var); },
|
||||
{"rect"sv, "radius"sv});
|
||||
addFunc ("closeSubpath"sv, [p] (auto var) { closeSubpath (p); });
|
||||
addFunc ("beginSubpath"sv, [p] (auto var) { beginSubpath (p, var); }, {"start"sv});
|
||||
}
|
||||
|
||||
static void addPath (const SharedPointer<CGraphicsPath>& path, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "path.addPath(path, transformMatrix?);"sv;
|
||||
auto otherPath = getGraphicsPath (var, "path"sv, signature);
|
||||
auto tm = getOptionalTransformMatrix (var, "transformMatrix?"sv, signature);
|
||||
path->addPath (*otherPath.get (), tm ? tm.get () : nullptr);
|
||||
}
|
||||
|
||||
static void addArc (const SharedPointer<CGraphicsPath>& path, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "path.addArc(rect, startAngle, endAngle, clockwise);"sv;
|
||||
auto rect = getRect (var, "rect"sv, signature);
|
||||
auto startAngle = getDouble (var, "startAngle"sv, signature);
|
||||
auto endAngle = getDouble (var, "endAngle"sv, signature);
|
||||
auto clockwise = getInt (var, "clockwise"sv, signature);
|
||||
path->addArc (rect, startAngle, endAngle, clockwise != 0 ? true : false);
|
||||
}
|
||||
|
||||
static void addEllipse (const SharedPointer<CGraphicsPath>& path, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "path.addEllipse(rect);"sv;
|
||||
auto rect = getRect (var, "rect"sv, signature);
|
||||
path->addEllipse (rect);
|
||||
}
|
||||
|
||||
static void addRect (const SharedPointer<CGraphicsPath>& path, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "path.addRect(rect);"sv;
|
||||
auto rect = getRect (var, "rect"sv, signature);
|
||||
path->addRect (rect);
|
||||
}
|
||||
|
||||
static void addLine (const SharedPointer<CGraphicsPath>& path, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "path.addLine(to);"sv;
|
||||
auto point = getPoint (var, "to"sv, signature);
|
||||
path->addLine (point);
|
||||
}
|
||||
|
||||
static void addBezierCurve (const SharedPointer<CGraphicsPath>& path, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "path.addBezierCurve(control1, control2, end);"sv;
|
||||
auto control1 = getPoint (var, "control1"sv, signature);
|
||||
auto control2 = getPoint (var, "control2"sv, signature);
|
||||
auto end = getPoint (var, "end"sv, signature);
|
||||
path->addBezierCurve (control1, control2, end);
|
||||
}
|
||||
|
||||
static void beginSubpath (const SharedPointer<CGraphicsPath>& path, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "path.beginSubpath(start);"sv;
|
||||
auto start = getPoint (var, "start"sv, signature);
|
||||
path->beginSubpath (start);
|
||||
}
|
||||
|
||||
static void closeSubpath (const SharedPointer<CGraphicsPath>& path)
|
||||
{
|
||||
static constexpr auto signature = "path.closeSubpath();"sv;
|
||||
path->closeSubpath ();
|
||||
}
|
||||
|
||||
static void addRoundRect (const SharedPointer<CGraphicsPath>& path, CScriptVar* var)
|
||||
{
|
||||
static constexpr auto signature = "path.addRoundRect(rect, radius);"sv;
|
||||
auto rect = getRect (var, "rect"sv, signature);
|
||||
auto radius = getDouble (var, "radius"sv, signature);
|
||||
path->addRoundRect (rect, radius);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
ScriptObject makeGraphicsPathScriptObject (const SharedPointer<CGraphicsPath>& p)
|
||||
{
|
||||
return GraphicsPathScriptObject (p);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct DrawContextObject::Impl
|
||||
{
|
||||
CDrawContext* context {nullptr};
|
||||
IUIDescription* uiDesc {nullptr};
|
||||
mutable int32_t globalStatesStored {0};
|
||||
|
||||
void setContext (CDrawContext* inContext, IUIDescription* inUIDesc)
|
||||
{
|
||||
if (context)
|
||||
{
|
||||
while (globalStatesStored > 0)
|
||||
{
|
||||
context->restoreGlobalState ();
|
||||
--globalStatesStored;
|
||||
}
|
||||
}
|
||||
context = inContext;
|
||||
uiDesc = inUIDesc;
|
||||
globalStatesStored = 0;
|
||||
}
|
||||
|
||||
void checkContextOrThrow () const
|
||||
{
|
||||
if (!context)
|
||||
throw CScriptException ("Native context is missing!");
|
||||
}
|
||||
|
||||
CDrawStyle getDrawStyle (CScriptVar* styleVar) const
|
||||
{
|
||||
CDrawStyle style {};
|
||||
auto string = styleVar->getString ();
|
||||
if (string == "stroked"sv)
|
||||
style = kDrawStroked;
|
||||
else if (string == "filled"sv)
|
||||
style = kDrawFilled;
|
||||
else if (string == "filledAndStroked"sv)
|
||||
style = kDrawFilledAndStroked;
|
||||
else
|
||||
throw CScriptException ("Unknown draw style: " + string);
|
||||
return style;
|
||||
}
|
||||
|
||||
CDrawContext::PathDrawMode getPathDrawMode (CScriptVar* var) const
|
||||
{
|
||||
CDrawContext::PathDrawMode mode {};
|
||||
auto string = var->getString ();
|
||||
if (string == "stroked"sv)
|
||||
mode = CDrawContext::PathDrawMode::kPathStroked;
|
||||
else if (string == "filled"sv)
|
||||
mode = CDrawContext::PathDrawMode::kPathFilled;
|
||||
else if (string == "filledEvenOdd"sv)
|
||||
mode = CDrawContext::PathDrawMode::kPathFilledEvenOdd;
|
||||
else
|
||||
throw CScriptException ("Unknown path draw mode: " + string);
|
||||
return mode;
|
||||
}
|
||||
|
||||
void createRoundGraphicsPath (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.createRoundGraphicsPath(rect, radius);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto rect = getRect (var, "rect"sv, signature);
|
||||
auto radius = getDouble (var, "radius"sv, signature);
|
||||
if (auto path = owned (context->createRoundRectGraphicsPath (rect, radius)))
|
||||
{
|
||||
GraphicsPathScriptObject obj (path);
|
||||
var->setReturnVar (obj);
|
||||
}
|
||||
}
|
||||
|
||||
void createGraphicsPath (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.createGraphicsPath();"sv;
|
||||
checkContextOrThrow ();
|
||||
if (auto path = owned (context->createGraphicsPath ()))
|
||||
{
|
||||
GraphicsPathScriptObject obj (path);
|
||||
var->setReturnVar (obj);
|
||||
}
|
||||
}
|
||||
|
||||
void createGradient (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature =
|
||||
"drawContext.createGradient(startColorPosition, startColor, endColorPosition, endColor);"sv;
|
||||
auto startColorPosition = getDouble (var, "startColorPosition", signature);
|
||||
auto endColorPosition = getDouble (var, "endColorPosition", signature);
|
||||
auto startColor = getColor (var, uiDesc, "startColor"sv, signature);
|
||||
auto endColor = getColor (var, uiDesc, "endColor"sv, signature);
|
||||
if (auto gradient = owned (
|
||||
CGradient::create (startColorPosition, endColorPosition, startColor, endColor)))
|
||||
{
|
||||
GradientScriptObject obj (gradient, uiDesc);
|
||||
var->setReturnVar (obj);
|
||||
}
|
||||
}
|
||||
|
||||
void drawGraphicsPath (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature =
|
||||
"drawContext.drawGraphicsPath(path, mode?, transform?);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto path = getGraphicsPath (var, "path"sv, signature);
|
||||
auto modeVar = getOptionalArgument (var, "mode?");
|
||||
auto mode = modeVar ? getPathDrawMode (modeVar) : CDrawContext::PathDrawMode::kPathFilled;
|
||||
auto tm = getOptionalTransformMatrix (var, "transform?"sv, signature);
|
||||
context->drawGraphicsPath (path, mode, tm ? tm.get () : nullptr);
|
||||
}
|
||||
|
||||
void fillLinearGradient (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature =
|
||||
"drawContext.fillLinearGradient(path, gradient, startPoint, endPoint, evenOdd?, transform?);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto path = getGraphicsPath (var, "path"sv, signature);
|
||||
auto gradient = getGradient (var, "gradient"sv, signature);
|
||||
auto startPoint = getPoint (var, "startPoint"sv, signature);
|
||||
auto endPoint = getPoint (var, "endPoint"sv, signature);
|
||||
auto tm = getOptionalTransformMatrix (var, "transform?"sv, signature);
|
||||
auto evenOdd = getOptionalInt (var, "evenOdd?", signature);
|
||||
context->fillLinearGradient (path, *gradient, startPoint, endPoint, evenOdd > 0, tm.get ());
|
||||
}
|
||||
|
||||
void fillRadialGradient (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature =
|
||||
"drawContext.fillRadialGradient(path, gradient, centerPoint, radius, originOffsetPoint?, evenOdd?, transform?);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto path = getGraphicsPath (var, "path"sv, signature);
|
||||
auto gradient = getGradient (var, "gradient"sv, signature);
|
||||
auto centerPoint = getPoint (var, "centerPoint"sv, signature);
|
||||
auto radius = getDouble (var, "radius"sv, signature);
|
||||
auto originOffsetPoint = getOptionalPoint (var, "originOffsetPoint?"sv, signature);
|
||||
auto evenOdd = getOptionalInt (var, "evenOdd?", signature);
|
||||
auto tm = getOptionalTransformMatrix (var, "transform?"sv, signature);
|
||||
context->fillRadialGradient (path, *gradient, centerPoint, radius, originOffsetPoint,
|
||||
evenOdd, tm.get ());
|
||||
}
|
||||
|
||||
void drawLine (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.drawLine(from, to);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto fromPoint = getArgument (var, "from"sv, signature);
|
||||
auto toPoint = getArgument (var, "to"sv, signature);
|
||||
auto from = fromScriptPoint (*fromPoint);
|
||||
auto to = fromScriptPoint (*toPoint);
|
||||
context->drawLine (from, to);
|
||||
}
|
||||
void drawRect (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.drawRect(rect, style);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto rect = getRect (var, "rect"sv, signature);
|
||||
auto styleVar = getArgument (var, "style"sv, signature);
|
||||
auto style = getDrawStyle (styleVar);
|
||||
context->drawRect (rect, style);
|
||||
}
|
||||
void drawEllipse (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.drawEllipse(rect, style);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto rect = getRect (var, "rect"sv, signature);
|
||||
auto styleVar = getArgument (var, "style"sv, signature);
|
||||
auto style = getDrawStyle (styleVar);
|
||||
context->drawEllipse (rect, style);
|
||||
}
|
||||
void drawArc (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature =
|
||||
"drawContext.drawArc(rect, startAngle, endAngle, style);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto rect = getRect (var, "rect"sv, signature);
|
||||
auto startAngle = static_cast<float> (getDouble (var, "startAngle"sv, signature));
|
||||
auto endAngle = static_cast<float> (getDouble (var, "endAngle"sv, signature));
|
||||
auto styleVar = getArgument (var, "style"sv, signature);
|
||||
auto style = getDrawStyle (styleVar);
|
||||
context->drawArc (rect, startAngle, endAngle, style);
|
||||
}
|
||||
void clearRect (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.clearRect(rect);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto rect = getRect (var, "rect"sv, signature);
|
||||
context->clearRect (rect);
|
||||
}
|
||||
void drawPolygon (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.drawPolygon(points, style);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto pointsVar = getArgument (var, "points"sv, signature);
|
||||
auto styleVar = getArgument (var, "style"sv, signature);
|
||||
if (!pointsVar->isArray ())
|
||||
throw CScriptException ("`points` argument must be an array of points in "
|
||||
"drawContext.drawPolygon(points, style);");
|
||||
PointList points;
|
||||
auto numPoints = pointsVar->getArrayLength ();
|
||||
for (auto index = 0; index < numPoints; ++index)
|
||||
{
|
||||
auto pointVar = pointsVar->getArrayIndex (index);
|
||||
vstgui_assert (pointVar != nullptr);
|
||||
points.emplace_back (fromScriptPoint (*pointVar));
|
||||
}
|
||||
auto style = getDrawStyle (styleVar);
|
||||
context->drawPolygon (points, style);
|
||||
}
|
||||
void setClipRect (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.setClipRect(rect);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto rect = getRect (var, "rect"sv, signature);
|
||||
context->setClipRect (rect);
|
||||
}
|
||||
void drawBitmap (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature =
|
||||
"drawContext.drawBitmap(name, destRect, offsetPoint?, alpha?);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto nameVar = getArgument (var, "name"sv, signature);
|
||||
auto destRect = getRect (var, "destRect"sv, signature);
|
||||
auto offsetPointVar = getOptionalArgument (var, "offsetPoint?"sv);
|
||||
auto alphaVar = getOptionalArgument (var, "alpha?"sv);
|
||||
auto bitmap = uiDesc->getBitmap (nameVar->getString ().data ());
|
||||
if (!bitmap)
|
||||
throw CScriptException ("bitmap not found in uiDescription");
|
||||
auto offset = offsetPointVar ? fromScriptPoint (*offsetPointVar) : CPoint (0, 0);
|
||||
auto alpha = static_cast<float> (alphaVar ? alphaVar->getDouble () : 1.);
|
||||
context->drawBitmap (bitmap, destRect, offset, alpha);
|
||||
}
|
||||
void drawString (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.drawString(string, rect, align?);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto stringVar = getArgument (var, "string"sv, signature);
|
||||
auto rect = getRect (var, "rect"sv, signature);
|
||||
auto alignVar = getOptionalArgument (var, "align?"sv);
|
||||
auto string = stringVar->getString ().data ();
|
||||
CHoriTxtAlign align = kCenterText;
|
||||
if (!alignVar || alignVar->isUndefined ())
|
||||
align = kCenterText;
|
||||
else if (alignVar->getString () == "left"sv)
|
||||
align = kLeftText;
|
||||
else if (alignVar->getString () == "center"sv)
|
||||
align = kCenterText;
|
||||
else if (alignVar->getString () == "right"sv)
|
||||
align = kRightText;
|
||||
else
|
||||
throw CScriptException (
|
||||
"wrong `align` argument. Expecting 'left', 'center' or 'right'");
|
||||
context->drawString (string, rect, align, true);
|
||||
}
|
||||
void setFont (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.setFont(name);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto fontVar = getArgument (var, "name"sv, signature);
|
||||
if (auto font = uiDesc->getFont (fontVar->getString ().data ()))
|
||||
context->setFont (font);
|
||||
}
|
||||
void setFontColor (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.setFontColor(color);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto colorVar = getArgument (var, "color"sv, signature);
|
||||
CColor color {};
|
||||
UIViewCreator::stringToColor (colorVar->getString (), color, uiDesc);
|
||||
context->setFontColor (color);
|
||||
}
|
||||
void setFillColor (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.setFillColor(color);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto color = getColor (var, uiDesc, "color"sv, signature);
|
||||
context->setFillColor (color);
|
||||
}
|
||||
void setFrameColor (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.setFrameColor(color);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto color = getColor (var, uiDesc, "color"sv, signature);
|
||||
context->setFrameColor (color);
|
||||
}
|
||||
void setLineWidth (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.setLineWidth(width);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto widthVar = getArgument (var, "width"sv, signature);
|
||||
context->setLineWidth (widthVar->getDouble ());
|
||||
}
|
||||
void setLineStyle (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature =
|
||||
"drawContext.setLineStyle(styleOrLineCap, lineJoin?, dashLengths?, dashPhase);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto styleOrLineCapVar = getArgument (var, "styleOrLineCap"sv, signature);
|
||||
auto lineJoinVar = getOptionalArgument (var, "lineJoin?"sv);
|
||||
auto dashLengthsVar = getOptionalArgument (var, "dashLengths?"sv);
|
||||
auto dashPhaseVar = getOptionalArgument (var, "dashPhase?"sv);
|
||||
auto styleOrLineCap = styleOrLineCapVar->getString ();
|
||||
std::unique_ptr<CLineStyle> lineStyle;
|
||||
if (styleOrLineCap == "solid"sv)
|
||||
{
|
||||
lineStyle = std::make_unique<CLineStyle> (kLineSolid);
|
||||
}
|
||||
else if (styleOrLineCap == "dotted"sv)
|
||||
{
|
||||
lineStyle = std::make_unique<CLineStyle> (kLineOnOffDash);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (styleOrLineCap == "butt"sv)
|
||||
lineStyle = std::make_unique<CLineStyle> (CLineStyle::LineCap::kLineCapButt);
|
||||
else if (styleOrLineCap == "round"sv)
|
||||
lineStyle = std::make_unique<CLineStyle> (CLineStyle::LineCap::kLineCapRound);
|
||||
else if (styleOrLineCap == "square"sv)
|
||||
lineStyle = std::make_unique<CLineStyle> (CLineStyle::LineCap::kLineCapSquare);
|
||||
else
|
||||
throw CScriptException ("unknown `line cap` argument");
|
||||
if (lineJoinVar)
|
||||
{
|
||||
auto lineJoin = lineJoinVar->getString ();
|
||||
if (lineJoin == "miter"sv)
|
||||
lineStyle->setLineJoin (CLineStyle::LineJoin::kLineJoinMiter);
|
||||
else if (lineJoin == "round"sv)
|
||||
lineStyle->setLineJoin (CLineStyle::LineJoin::kLineJoinRound);
|
||||
else if (lineJoin == "bevel"sv)
|
||||
lineStyle->setLineJoin (CLineStyle::LineJoin::kLineJoinBevel);
|
||||
}
|
||||
if (dashLengthsVar)
|
||||
{
|
||||
if (!dashLengthsVar->isArray ())
|
||||
throw CScriptException ("`dashLengths` must be an array of numbers");
|
||||
CLineStyle::CoordVector lengths;
|
||||
auto numValues = dashLengthsVar->getArrayLength ();
|
||||
for (auto index = 0; index < numValues; ++index)
|
||||
{
|
||||
if (auto lengthVar = dashLengthsVar->getArrayIndex (index))
|
||||
lengths.push_back (lengthVar->getDouble ());
|
||||
}
|
||||
lineStyle->getDashLengths () = lengths;
|
||||
}
|
||||
if (dashPhaseVar)
|
||||
{
|
||||
lineStyle->setDashPhase (dashPhaseVar->getDouble ());
|
||||
}
|
||||
}
|
||||
if (lineStyle)
|
||||
context->setLineStyle (*lineStyle.get ());
|
||||
}
|
||||
void setGlobalAlpha (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.setGlobalAlpha(alpha);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto alpha = static_cast<float> (getDouble (var, "alpha"sv, signature));
|
||||
context->setGlobalAlpha (alpha);
|
||||
}
|
||||
void saveGlobalState () const
|
||||
{
|
||||
checkContextOrThrow ();
|
||||
context->saveGlobalState ();
|
||||
++globalStatesStored;
|
||||
}
|
||||
void restoreGlobalState () const
|
||||
{
|
||||
checkContextOrThrow ();
|
||||
context->restoreGlobalState ();
|
||||
--globalStatesStored;
|
||||
}
|
||||
void getStringWidth (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.getStringWidth(string);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto stringVar = getArgument (var, "string"sv, signature);
|
||||
auto width = context->getStringWidth (stringVar->getString ().data ());
|
||||
var->getReturnVar ()->setDouble (width);
|
||||
}
|
||||
void setDrawMode (CScriptVar* var) const
|
||||
{
|
||||
static constexpr auto signature = "drawContext.setDrawMode(mode);"sv;
|
||||
checkContextOrThrow ();
|
||||
auto modeVar = getArgument (var, "mode"sv, signature);
|
||||
if (modeVar->getString () == "aliasing"sv)
|
||||
context->setDrawMode (kAliasing);
|
||||
else if (modeVar->getString () == "anti-aliasing"sv)
|
||||
context->setDrawMode (kAntiAliasing);
|
||||
else
|
||||
throw CScriptException ("`mode` must be `aliasing` or `anti-aliasing`");
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
DrawContextObject::DrawContextObject ()
|
||||
{
|
||||
impl = std::make_unique<Impl> ();
|
||||
scriptVar->setLifeTimeObserver (this);
|
||||
addFunc ("clearRect"sv, [this] (auto var) { impl->clearRect (var); }, {"rect"sv});
|
||||
addFunc ("createRoundGraphicsPath"sv,
|
||||
[this] (auto var) { impl->createRoundGraphicsPath (var); }, {"rect"sv, "radius"sv});
|
||||
addFunc ("createGraphicsPath"sv, [this] (auto var) { impl->createGraphicsPath (var); });
|
||||
addFunc ("createGradient"sv, [this] (auto var) { impl->createGradient (var); },
|
||||
{"startColorPosition"sv, "startColor"sv, "endColorPosition"sv, "endColor"sv});
|
||||
addFunc ("getStringWidth"sv, [this] (auto var) { impl->getStringWidth (var); }, {"string"sv});
|
||||
addFunc ("drawArc"sv, [this] (auto var) { impl->drawArc (var); },
|
||||
{"rect"sv, "startAngle"sv, "endAngle"sv, "style"sv});
|
||||
addFunc ("drawBitmap"sv, [this] (auto var) { impl->drawBitmap (var); },
|
||||
{"name"sv, "destRect"sv, "offsetPoint?"sv, "alpha?"sv});
|
||||
addFunc ("drawEllipse"sv, [this] (auto var) { impl->drawEllipse (var); },
|
||||
{"rect"sv, "style"sv});
|
||||
addFunc ("drawGraphicsPath"sv, [this] (auto var) { impl->drawGraphicsPath (var); },
|
||||
{"path"sv, "mode?"sv, "transform?"sv});
|
||||
addFunc ("drawLine"sv, [this] (auto var) { impl->drawLine (var); }, {"from"sv, "to"sv});
|
||||
addFunc ("drawPolygon"sv, [this] (auto var) { impl->drawPolygon (var); },
|
||||
{"points"sv, "style"sv});
|
||||
addFunc ("drawRect"sv, [this] (auto var) { impl->drawRect (var); }, {"rect"sv, "style"sv});
|
||||
addFunc ("drawString"sv, [this] (auto var) { impl->drawString (var); },
|
||||
{"string"sv, "rect"sv, "align?"sv});
|
||||
addFunc ("fillLinearGradient"sv, [this] (auto var) { impl->fillLinearGradient (var); },
|
||||
{"path"sv, "gradient"sv, "startPoint"sv, "endPoint"sv, "evenOdd?"sv, "transform?"sv});
|
||||
addFunc ("fillRadialGradient"sv, [this] (auto var) { impl->fillRadialGradient (var); },
|
||||
{"path"sv, "gradient"sv, "centerPoint"sv, "radius"sv, "originOffsetPoint?"sv,
|
||||
"evenOdd?"sv, "transform?"sv});
|
||||
addFunc ("restoreGlobalState"sv, [this] (auto var) { impl->restoreGlobalState (); });
|
||||
addFunc ("saveGlobalState"sv, [this] (auto var) { impl->saveGlobalState (); });
|
||||
addFunc ("setClipRect"sv, [this] (auto var) { impl->setClipRect (var); }, {"rect"sv});
|
||||
addFunc ("setFont"sv, [this] (auto var) { impl->setFont (var); }, {"name"sv});
|
||||
addFunc ("setFontColor"sv, [this] (auto var) { impl->setFontColor (var); }, {"color"sv});
|
||||
addFunc ("setFillColor"sv, [this] (auto var) { impl->setFillColor (var); }, {"color"sv});
|
||||
addFunc ("setFrameColor"sv, [this] (auto var) { impl->setFrameColor (var); }, {"color"sv});
|
||||
addFunc ("setGlobalAlpha", [this] (auto var) { impl->setGlobalAlpha (var); }, {"alpha"sv});
|
||||
addFunc ("setLineWidth"sv, [this] (auto var) { impl->setLineWidth (var); }, {"width"sv});
|
||||
addFunc ("setLineStyle"sv, [this] (auto var) { impl->setLineStyle (var); },
|
||||
{"styleOrLineCap"sv, "lineJoin?"sv, "dashLengths?"sv, "dashPhase?"sv});
|
||||
addFunc ("setDrawMode"sv, [this] (auto var) { impl->setDrawMode (var); }, {"mode"sv});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
DrawContextObject::~DrawContextObject () noexcept
|
||||
{
|
||||
if (scriptVar)
|
||||
scriptVar->setLifeTimeObserver (nullptr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void DrawContextObject::setDrawContext (CDrawContext* inContext, IUIDescription* inUIDesc)
|
||||
{
|
||||
impl->setContext (inContext, inUIDesc);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void DrawContextObject::onDestroy (CScriptVar* v)
|
||||
{
|
||||
v->setLifeTimeObserver (nullptr);
|
||||
scriptVar = nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // ScriptingInternal
|
||||
} // VSTGUI
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
// 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 "scriptobject.h"
|
||||
#include "../../lib/vstguifwd.h"
|
||||
#include "../../uidescription/uidescriptionfwd.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace ScriptingInternal {
|
||||
|
||||
TJS::CScriptVar* makeTransformMatrixObject ();
|
||||
ScriptObject makeGraphicsPathScriptObject (const SharedPointer<CGraphicsPath>& p);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct DrawContextObject : ScriptObject,
|
||||
TJS::IScriptVarLifeTimeObserver
|
||||
{
|
||||
DrawContextObject ();
|
||||
~DrawContextObject () noexcept override;
|
||||
|
||||
void setDrawContext (CDrawContext* context, IUIDescription* uiDesc);
|
||||
|
||||
void onDestroy (CScriptVar* v) override;
|
||||
|
||||
private:
|
||||
// CanvasRenderingContext2D API
|
||||
// clang-format off
|
||||
/*
|
||||
fillStyle: string | CanvasGradient | CanvasPattern;
|
||||
filter: string
|
||||
font: string;
|
||||
fontKerning: string;
|
||||
fontStretch: string;
|
||||
fontVariantCaps: string;
|
||||
globalAlpha: number;
|
||||
globalCompositionOperation: string;
|
||||
lineCap: string;
|
||||
lineDashOffset: number;
|
||||
lineJoin: string;
|
||||
lineWidth: number;
|
||||
miterLimit: number;
|
||||
shadowBlur: number;
|
||||
shadowColor: string;
|
||||
shadowOffsetX: number;
|
||||
shadowOffsetY: number;
|
||||
strokeStyle: string;
|
||||
textAlign: string;
|
||||
textBaseline: string;
|
||||
arc: (x: number, y: number, r: number, sAngle: number, eAngle: number, counterClockwise?: boolean) => void;
|
||||
arcTo: (x1: number, y1: number, x2: number, y2: number, r: number) => void;
|
||||
beginPath: () => void;
|
||||
bezierCurveTo: (cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number) => void;
|
||||
clearRect: (x: number, y: number, width: number, height: number) => void;
|
||||
clip: () => void;
|
||||
closePath: () => void;
|
||||
createImageData: (width: number, height: number, imageData: ImageData) => void;
|
||||
createLinearGradient: (x0: number, yo: number, x1: number, y1: number) => CanvasGradient;
|
||||
createPattern: () => CanvasPattern;
|
||||
createRadialGradient: (x0: number, y0: number, r0: number, x1: number, y1: number, r1: number) => CanvasGradient;
|
||||
drawFocusIfNeeded: (html: HTMLElement) => void;
|
||||
drawImage: (image: Image,dx: number,dy: number,sx?: number,sy?: number,sWidth?: number,sHeight?: number,dWidth?: number,dHeight?: number) => void;
|
||||
ellipse: (x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, anticlockwise?: boolean) => void;
|
||||
fill: (Path2D?: Path2D, fillRule?: any) => void;
|
||||
fillRect: (x: number, y: number, width: number, height: number) => void;
|
||||
fillText: (text: string, x: number, y: number, maxWidth?: number) => void;
|
||||
getImageData: (sx: number, sy: number, sw: number, sh: number) => Promise<ImageData>;
|
||||
getLineDash: () => number[];
|
||||
isPointInPath: (x: number, y: number, fillRule: any, path: Path2D) => boolean;
|
||||
isPointInStroke: (x: number, y: number, path: Path2D) => boolean;
|
||||
lineTo: (x: number, y: number) => void;
|
||||
measureText: (text: string) => any;
|
||||
moveTo: (x: number, y: number) => void;
|
||||
putImageData: (imageData: ImageData, dx: number, dy: number, dirtyX?: number, dirtyY?: number, dirtyWidth?: number, dirtyHeight?: number) => void;
|
||||
quadraticCurveTo: (cpx: number, cpy: number, x: number, y: number) => void;
|
||||
rect: (x: number, y: number, width: number, height: number) => void;
|
||||
reset: () => void
|
||||
resetTransform: () => void
|
||||
restore: () => void;
|
||||
rotate: (angle: number) => void;
|
||||
roundRect: (x: number, y: number, width: number, height: number, radii: number) => void
|
||||
save: () => void;
|
||||
scale: (x: number, y: number) => void;
|
||||
setLineDash: (segments: number[]) => void;
|
||||
setTransform: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||
stroke: (path?: Path2D) => void;
|
||||
strokeRect: (x: number, y: number, width: number, height: number) => void;
|
||||
strokeText: (text: string, x: number, y: number, maxWidth?: number) => void;
|
||||
transform: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||
translate: (x: number, y: number) => void;
|
||||
*/
|
||||
// clang-format on
|
||||
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // ScriptingInternal
|
||||
} // VSTGUI
|
||||
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
// 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 "../uiscripting.h"
|
||||
#include <string>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace ScriptingInternal {
|
||||
|
||||
static const std::string kAttrScript = "script";
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct IScriptContextInternal : public IScriptContext
|
||||
{
|
||||
virtual void onViewCreated (CView* view, const std::string& script) = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // ScriptingInternal
|
||||
} // VSTGUI
|
||||
Vendored
+133
@@ -0,0 +1,133 @@
|
||||
// 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
|
||||
|
||||
#include "scriptingviewfactory.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace ScriptingInternal {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
JavaScriptViewFactory::JavaScriptViewFactory (IScriptContextInternal* scripting,
|
||||
IViewFactory* origFactory)
|
||||
: Super (origFactory), scriptContext (scripting)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
JavaScriptViewFactory::~JavaScriptViewFactory () noexcept
|
||||
{
|
||||
std::for_each (viewControllerLinks.begin (), viewControllerLinks.end (),
|
||||
[this] (const auto& el) {
|
||||
el.first->unregisterViewListener (this);
|
||||
el.second->scriptContextDestroyed (scriptContext);
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
CView* JavaScriptViewFactory::createView (const UIAttributes& attributes,
|
||||
const IUIDescription* description) const
|
||||
{
|
||||
if (auto view = Super::createView (attributes, description))
|
||||
{
|
||||
if (auto value = attributes.getAttributeValue (kAttrScript))
|
||||
{
|
||||
std::optional<std::string> verifiedScript;
|
||||
if (auto scriptViewController =
|
||||
dynamic_cast<IScriptControllerExtension*> (description->getController ()))
|
||||
{
|
||||
verifiedScript = scriptViewController->verifyScript (view, *value, scriptContext);
|
||||
view->registerViewListener (const_cast<JavaScriptViewFactory*> (this));
|
||||
viewControllerLinks.emplace_back (view, scriptViewController);
|
||||
}
|
||||
const auto& script = verifiedScript ? *verifiedScript : *value;
|
||||
auto scriptSize = static_cast<uint32_t> (script.size () + 1);
|
||||
view->setAttribute (scriptAttrID, scriptSize, script.data ());
|
||||
if (!disabled)
|
||||
{
|
||||
scriptContext->onViewCreated (view, script);
|
||||
}
|
||||
}
|
||||
return view;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool JavaScriptViewFactory::getAttributeNamesForView (CView* view, StringList& attributeNames) const
|
||||
{
|
||||
if (Super::getAttributeNamesForView (view, attributeNames))
|
||||
{
|
||||
attributeNames.emplace_back (kAttrScript);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
auto JavaScriptViewFactory::getAttributeType (CView* view, const std::string& attributeName) const
|
||||
-> IViewCreator::AttrType
|
||||
{
|
||||
if (attributeName == kAttrScript)
|
||||
return IViewCreator::kScriptType;
|
||||
return Super::getAttributeType (view, attributeName);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool JavaScriptViewFactory::getAttributeValue (CView* view, const std::string& attributeName,
|
||||
std::string& stringValue,
|
||||
const IUIDescription* desc) const
|
||||
{
|
||||
if (attributeName == kAttrScript)
|
||||
{
|
||||
uint32_t attrSize = 0;
|
||||
if (view->getAttributeSize (scriptAttrID, attrSize) && attrSize > 0)
|
||||
{
|
||||
stringValue.resize (attrSize - 1);
|
||||
if (!view->getAttribute (scriptAttrID, attrSize, stringValue.data (), attrSize))
|
||||
stringValue = "";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return Super::getAttributeValue (view, attributeName, stringValue, desc);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool JavaScriptViewFactory::applyAttributeValues (CView* view, const UIAttributes& attributes,
|
||||
const IUIDescription* desc) const
|
||||
{
|
||||
if (auto value = attributes.getAttributeValue (kAttrScript))
|
||||
{
|
||||
if (value->empty ())
|
||||
view->removeAttribute (scriptAttrID);
|
||||
else
|
||||
view->setAttribute (scriptAttrID, static_cast<uint32_t> (value->size () + 1),
|
||||
value->data ());
|
||||
if (!disabled)
|
||||
scriptContext->onViewCreated (view, *value);
|
||||
return true;
|
||||
}
|
||||
return Super::applyAttributeValues (view, attributes, desc);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void JavaScriptViewFactory::setScriptingDisabled (bool state) { disabled = state; }
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void JavaScriptViewFactory::viewWillDelete (CView* view)
|
||||
{
|
||||
auto it = std::find_if (viewControllerLinks.begin (), viewControllerLinks.end (),
|
||||
[view] (const auto& el) { return el.first == view; });
|
||||
if (it != viewControllerLinks.end ())
|
||||
{
|
||||
it->second->scriptContextDestroyed (scriptContext);
|
||||
viewControllerLinks.erase (it);
|
||||
}
|
||||
view->unregisterViewListener (this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // ScriptingInternal
|
||||
} // VSTGUI
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
// 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 "iscriptcontextinternal.h"
|
||||
#include "../../uidescription/uiattributes.h"
|
||||
#include "../../uidescription/uiviewfactory.h"
|
||||
#include "../../lib/iviewlistener.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace ScriptingInternal {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct JavaScriptViewFactory : ViewFactoryDelegate,
|
||||
ViewListenerAdapter
|
||||
{
|
||||
static constexpr CViewAttributeID scriptAttrID = 'scri';
|
||||
|
||||
JavaScriptViewFactory (ScriptingInternal::IScriptContextInternal* scripting,
|
||||
IViewFactory* origFactory);
|
||||
~JavaScriptViewFactory () noexcept;
|
||||
|
||||
CView* createView (const UIAttributes& attributes,
|
||||
const IUIDescription* description) const override;
|
||||
bool getAttributeNamesForView (CView* view, StringList& attributeNames) const override;
|
||||
IViewCreator::AttrType getAttributeType (CView* view,
|
||||
const std::string& attributeName) const override;
|
||||
bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue,
|
||||
const IUIDescription* desc) const override;
|
||||
bool applyAttributeValues (CView* view, const UIAttributes& attributes,
|
||||
const IUIDescription* desc) const override;
|
||||
void setScriptingDisabled (bool state);
|
||||
|
||||
private:
|
||||
void viewWillDelete (CView* view) override;
|
||||
|
||||
using Super = ViewFactoryDelegate;
|
||||
using ViewControllerLink = std::pair<CView*, IScriptControllerExtension*>;
|
||||
using ViewControllerLinkVector = std::vector<ViewControllerLink>;
|
||||
|
||||
ScriptingInternal::IScriptContextInternal* scriptContext;
|
||||
mutable ViewControllerLinkVector viewControllerLinks;
|
||||
bool disabled {false};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // ScriptingInternal
|
||||
} // VSTGUI
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
// 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
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
// 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 "scriptobject.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace ScriptingInternal {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct UIDescScriptObject : ScriptObject
|
||||
{
|
||||
using StringList = std::list<const std::string*>;
|
||||
using CScriptException = TJS::CScriptException;
|
||||
|
||||
UIDescScriptObject () = default;
|
||||
UIDescScriptObject (IUIDescription* desc, TJS::CTinyJS* scriptContext)
|
||||
{
|
||||
using namespace std::literals;
|
||||
|
||||
addFunc ("colorNames"sv, [desc] (CScriptVar* var) {
|
||||
StringList names;
|
||||
desc->collectColorNames (names);
|
||||
var->setReturnVar (createArrayFromNames (names));
|
||||
});
|
||||
addFunc ("fontNames"sv, [desc] (CScriptVar* var) {
|
||||
StringList names;
|
||||
desc->collectFontNames (names);
|
||||
var->setReturnVar (createArrayFromNames (names));
|
||||
});
|
||||
addFunc ("bitmapNames"sv, [desc] (CScriptVar* var) {
|
||||
StringList names;
|
||||
desc->collectBitmapNames (names);
|
||||
var->setReturnVar (createArrayFromNames (names));
|
||||
});
|
||||
addFunc ("gradientNames"sv, [desc] (CScriptVar* var) {
|
||||
StringList names;
|
||||
desc->collectGradientNames (names);
|
||||
var->setReturnVar (createArrayFromNames (names));
|
||||
});
|
||||
addFunc ("controlTagNames"sv, [desc] (CScriptVar* var) {
|
||||
StringList names;
|
||||
desc->collectControlTagNames (names);
|
||||
var->setReturnVar (createArrayFromNames (names));
|
||||
});
|
||||
addFunc ("getTagForName"sv,
|
||||
[desc] (CScriptVar* var) {
|
||||
auto param = var->getParameter ("name"sv);
|
||||
if (!param)
|
||||
{
|
||||
throw CScriptException ("Expect 'name' argument for getTagForName ");
|
||||
}
|
||||
auto name = param->getString ();
|
||||
auto tag = desc->getTagForName (name.data ());
|
||||
var->setReturnVar (new CScriptVar (static_cast<int64_t> (tag)));
|
||||
},
|
||||
{"name"});
|
||||
addFunc ("lookupTagName"sv,
|
||||
[desc] (CScriptVar* var) {
|
||||
auto param = var->getParameter ("tag"sv);
|
||||
if (!param)
|
||||
{
|
||||
throw CScriptException ("Expect 'tag' argument for lookupTagName ");
|
||||
}
|
||||
if (!param->isInt ())
|
||||
{
|
||||
throw CScriptException ("Expect 'tag' argument to be an integer ");
|
||||
}
|
||||
if (auto tagName =
|
||||
desc->lookupControlTagName (static_cast<int32_t> (param->getInt ())))
|
||||
{
|
||||
var->setReturnVar (new CScriptVar (std::string (tagName)));
|
||||
}
|
||||
},
|
||||
{"tag"});
|
||||
}
|
||||
|
||||
static CScriptVar* createArrayFromNames (const StringList& names)
|
||||
{
|
||||
auto array = new CScriptVar ();
|
||||
array->setArray ();
|
||||
int index = 0;
|
||||
for (auto name : names)
|
||||
{
|
||||
array->addChild (std::to_string (index), new CScriptVar (*name));
|
||||
++index;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // ScriptingInternal
|
||||
} // VSTGUI
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
// 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
|
||||
|
||||
#include "viewscriptobject.h"
|
||||
#include "converters.h"
|
||||
#include "drawable.h"
|
||||
#include "../uiscripting.h"
|
||||
#include "../../uidescription/iviewfactory.h"
|
||||
#include "../../uidescription/uiattributes.h"
|
||||
#include "../../lib/cview.h"
|
||||
#include "../../lib/controls/ccontrol.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace ScriptingInternal {
|
||||
|
||||
using namespace std::literals;
|
||||
using namespace TJS;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
ViewScriptObject::ViewScriptObject (CView* view, IViewScriptObjectContext* context)
|
||||
: view (view), context (context)
|
||||
{
|
||||
scriptVar->setLifeTimeObserver (this);
|
||||
auto viewType = IViewFactory::getViewName (view);
|
||||
scriptVar->addChild ("type"sv, new CScriptVar (std::string (viewType ? viewType : "unknown")));
|
||||
addFunc ("setAttribute"sv,
|
||||
[uiDesc = context->getUIDescription (), view] (CScriptVar* var) {
|
||||
auto key = var->getParameter ("key"sv);
|
||||
auto value = var->getParameter ("value"sv);
|
||||
UIAttributes attr;
|
||||
attr.setAttribute (key->getString ().data (), value->getString ().data ());
|
||||
auto result = uiDesc->getViewFactory ()->applyAttributeValues (view, attr, uiDesc);
|
||||
var->getReturnVar ()->setInt (result);
|
||||
},
|
||||
{"key", "value"});
|
||||
addFunc ("getAttribute"sv,
|
||||
[uiDesc = context->getUIDescription (), view] (CScriptVar* var) {
|
||||
auto key = var->getParameter ("key"sv);
|
||||
std::string result;
|
||||
if (uiDesc->getViewFactory ()->getAttributeValue (view, key->getString ().data (),
|
||||
result, uiDesc))
|
||||
{
|
||||
var->getReturnVar ()->setString (result);
|
||||
}
|
||||
else
|
||||
{
|
||||
var->getReturnVar ()->setUndefined ();
|
||||
}
|
||||
},
|
||||
{"key"});
|
||||
addFunc ("isTypeOf"sv,
|
||||
[uiDesc = context->getUIDescription (), view] (CScriptVar* var) {
|
||||
auto typeName = var->getParameter ("typeName"sv);
|
||||
auto result =
|
||||
uiDesc->getViewFactory ()->viewIsTypeOf (view, typeName->getString ().data ());
|
||||
var->getReturnVar ()->setInt (result);
|
||||
},
|
||||
{"typeName"});
|
||||
addFunc ("invalid"sv, [view] (CScriptVar* var) { view->invalid (); });
|
||||
addFunc ("invalidRect"sv,
|
||||
[view] (CScriptVar* var) {
|
||||
auto rectVar = var->getParameter ("rect"sv);
|
||||
if (!rectVar)
|
||||
throw CScriptException ("Missing 'rect' argument in view.invalidRect(rect) ");
|
||||
auto rect = fromScriptRect (*rectVar);
|
||||
view->invalidRect (rect);
|
||||
},
|
||||
{"rect"});
|
||||
addFunc ("getBounds"sv, [view] (CScriptVar* var) {
|
||||
auto bounds = view->getViewSize ();
|
||||
bounds.originize ();
|
||||
var->setReturnVar (makeScriptRect (bounds));
|
||||
});
|
||||
addFunc ("getParent"sv, [view, context] (CScriptVar* var) {
|
||||
auto parentView = view->getParentView ();
|
||||
if (!parentView)
|
||||
{
|
||||
var->getReturnVar ()->setUndefined ();
|
||||
return;
|
||||
}
|
||||
auto obj = context->addView (parentView);
|
||||
vstgui_assert (obj);
|
||||
var->setReturnVar (obj->getVar ());
|
||||
obj->getVar ()->release ();
|
||||
});
|
||||
addFunc ("getControllerProperty"sv,
|
||||
[view] (CScriptVar* var) {
|
||||
auto viewController = getViewController (view, true);
|
||||
auto controller = dynamic_cast<IScriptControllerExtension*> (viewController);
|
||||
auto name = var->getParameter ("name"sv);
|
||||
if (!controller || !name)
|
||||
{
|
||||
var->getReturnVar ()->setUndefined ();
|
||||
return;
|
||||
}
|
||||
IScriptControllerExtension::PropertyValue value;
|
||||
if (!controller->getProperty (view, name->getString (), value))
|
||||
{
|
||||
var->getReturnVar ()->setUndefined ();
|
||||
return;
|
||||
}
|
||||
std::visit (
|
||||
[&] (auto&& value) {
|
||||
using T = std::decay_t<decltype (value)>;
|
||||
if constexpr (std::is_same_v<T, int64_t>)
|
||||
var->getReturnVar ()->setInt (value);
|
||||
else if constexpr (std::is_same_v<T, double>)
|
||||
var->getReturnVar ()->setDouble (value);
|
||||
else if constexpr (std::is_same_v<T, std::string>)
|
||||
var->getReturnVar ()->setString (value);
|
||||
else if constexpr (std::is_same_v<T, std::nullptr_t>)
|
||||
var->getReturnVar ()->setUndefined ();
|
||||
},
|
||||
value);
|
||||
},
|
||||
{"name"});
|
||||
addFunc ("setControllerProperty"sv,
|
||||
[view] (CScriptVar* var) {
|
||||
auto viewController = getViewController (view, true);
|
||||
auto controller = dynamic_cast<IScriptControllerExtension*> (viewController);
|
||||
auto name = var->getParameter ("name"sv);
|
||||
auto value = var->getParameter ("value"sv);
|
||||
if (!controller || !name || !value || !(value->isNumeric () || value->isString ()))
|
||||
{
|
||||
var->getReturnVar ()->setUndefined ();
|
||||
return;
|
||||
}
|
||||
IScriptControllerExtension::PropertyValue propValue;
|
||||
if (value->isInt ())
|
||||
propValue = value->getInt ();
|
||||
else if (value->isDouble ())
|
||||
propValue = value->getDouble ();
|
||||
else if (value->isString ())
|
||||
propValue = value->getString ().data ();
|
||||
auto result = controller->setProperty (view, name->getString (), propValue);
|
||||
var->getReturnVar ()->setInt (result);
|
||||
},
|
||||
{"name", "value"});
|
||||
if (auto control = dynamic_cast<CControl*> (view))
|
||||
{
|
||||
addFunc ("setValue"sv,
|
||||
[control] (CScriptVar* var) {
|
||||
auto value = var->getParameter ("value"sv);
|
||||
if (value->isNumeric ())
|
||||
{
|
||||
auto oldValue = control->getValue ();
|
||||
control->setValue (static_cast<float> (value->getDouble ()));
|
||||
if (oldValue != control->getValue ())
|
||||
control->valueChanged ();
|
||||
}
|
||||
},
|
||||
{"value"});
|
||||
addFunc ("getValue"sv, [control] (CScriptVar* var) {
|
||||
var->getReturnVar ()->setDouble (control->getValue ());
|
||||
});
|
||||
addFunc ("setValueNormalized"sv,
|
||||
[control] (CScriptVar* var) {
|
||||
auto value = var->getParameter ("value"sv);
|
||||
if (value->isNumeric ())
|
||||
{
|
||||
auto oldValue = control->getValue ();
|
||||
control->setValueNormalized (static_cast<float> (value->getDouble ()));
|
||||
if (oldValue != control->getValue ())
|
||||
control->valueChanged ();
|
||||
}
|
||||
},
|
||||
{"value"});
|
||||
addFunc ("getValueNormalized"sv, [control] (CScriptVar* var) {
|
||||
var->getReturnVar ()->setDouble (control->getValueNormalized ());
|
||||
});
|
||||
addFunc ("beginEdit"sv, [control] (CScriptVar* var) { control->beginEdit (); });
|
||||
addFunc ("endEdit"sv, [control] (CScriptVar* var) { control->endEdit (); });
|
||||
addFunc ("getMinValue"sv, [control] (CScriptVar* var) {
|
||||
var->getReturnVar ()->setDouble (control->getMin ());
|
||||
});
|
||||
addFunc ("getMaxValue"sv, [control] (CScriptVar* var) {
|
||||
var->getReturnVar ()->setDouble (control->getMax ());
|
||||
});
|
||||
addFunc ("getTag"sv, [control] (CScriptVar* var) {
|
||||
var->getReturnVar ()->setInt (control->getTag ());
|
||||
});
|
||||
}
|
||||
if (auto drawable = dynamic_cast<JavaScriptDrawable*> (view))
|
||||
drawable->setup (this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
ViewScriptObject::~ViewScriptObject () noexcept
|
||||
{
|
||||
if (scriptVar)
|
||||
scriptVar->setLifeTimeObserver (nullptr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void ViewScriptObject::onDestroy (CScriptVar* v)
|
||||
{
|
||||
v->setLifeTimeObserver (nullptr);
|
||||
scriptVar = nullptr;
|
||||
if (context)
|
||||
context->removeView (view);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // ScriptingInternal
|
||||
} // VSTGUI
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
// 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 "scriptobject.h"
|
||||
#include "../../lib/vstguifwd.h"
|
||||
#include "../../uidescription/iuidescription.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace ScriptingInternal {
|
||||
|
||||
struct IViewScriptObjectContext;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct ViewScriptObject : ScriptObject,
|
||||
TJS::IScriptVarLifeTimeObserver
|
||||
{
|
||||
ViewScriptObject (CView* view, IViewScriptObjectContext* context);
|
||||
~ViewScriptObject () noexcept;
|
||||
|
||||
IViewScriptObjectContext* getContext () const { return context; }
|
||||
|
||||
void onDestroy (CScriptVar* v) override;
|
||||
|
||||
private:
|
||||
CView* view {nullptr};
|
||||
IViewScriptObjectContext* context {nullptr};
|
||||
};
|
||||
|
||||
using ViewScriptMap = std::unordered_map<CView*, std::unique_ptr<ViewScriptObject>>;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct IViewScriptObjectContext
|
||||
{
|
||||
virtual ~IViewScriptObjectContext () = default;
|
||||
|
||||
virtual IUIDescription* getUIDescription () const = 0;
|
||||
virtual ViewScriptObject* addView (CView* view) = 0;
|
||||
virtual ViewScriptMap::iterator removeView (CView* view) = 0;
|
||||
virtual ScriptObject evalScript (std::string_view script) noexcept = 0;
|
||||
virtual TJS::CScriptVar* getRoot () const = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // ScriptingInternal
|
||||
} // VSTGUI
|
||||
Reference in New Issue
Block a user