Skip to content

Commit

Permalink
clean up and some more doc
Browse files Browse the repository at this point in the history
  • Loading branch information
scheffle committed Oct 20, 2024
1 parent 9b5805a commit eac1ed2
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 26 deletions.
48 changes: 37 additions & 11 deletions vstgui/uidescription-scripting/detail/drawable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ void JavaScriptDrawable::onDraw (CDrawContext* context, const CRect& rect, const

auto rectVar = makeScriptRect (rect);
auto scriptRoot = scriptContext->getRoot ();
ScriptAddChildScoped scs (*scriptRoot, "view", *scriptObject);
ScriptAddChildScoped scs2 (*scriptRoot, "context", drawContext);
ScriptAddChildScoped scs3 (*scriptRoot, "rect", rectVar);
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);
Expand All @@ -72,8 +72,11 @@ bool JavaScriptDrawable::onDrawFocusOnTop ()
if (!scriptContext)
return false;

if (scriptObject->getVar ()->findChild ("drawFocusOnTop"sv) == nullptr)
return false;

auto scriptRoot = scriptContext->getRoot ();
ScriptAddChildScoped scs (*scriptRoot, "view", *scriptObject);
ScriptAddChildScoped scs (*scriptRoot, "view"sv, *scriptObject);
auto boolResult = scriptContext->evalScript ("view.drawFocusOnTop();"sv);
return boolResult->isNumeric () ? boolResult->getInt () : false;
}
Expand All @@ -84,13 +87,22 @@ bool JavaScriptDrawable::onGetFocusPath (CGraphicsPath& outPath, CCoord focusWid
{
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", *scriptObject);
ScriptAddChildScoped scs2 (*scriptRoot, "path", makeGraphicsPathScriptObject (path));
ScriptAddChildScoped scs3 (*scriptRoot, "focusWidth", focusWidthVar);
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 ())
{
Expand All @@ -116,12 +128,19 @@ void JavaScriptDrawableView::drawRect (CDrawContext* context, const CRect& rect)
}

//------------------------------------------------------------------------
bool JavaScriptDrawableView::drawFocusOnTop () { return onDrawFocusOnTop (); }
bool JavaScriptDrawableView::drawFocusOnTop ()
{
if (wantsFocus ())
return onDrawFocusOnTop ();
return false;
}

//------------------------------------------------------------------------
bool JavaScriptDrawableView::getFocusPath (CGraphicsPath& outPath)
{
return onGetFocusPath (outPath, getFrame ()->getFocusWidth (), getViewSize ());
if (wantsFocus ())
return onGetFocusPath (outPath, getFrame ()->getFocusWidth (), getViewSize ());
return false;
}

//------------------------------------------------------------------------
Expand All @@ -136,12 +155,19 @@ void JavaScriptDrawableControl::drawRect (CDrawContext* context, const CRect& re
}

//------------------------------------------------------------------------
bool JavaScriptDrawableControl::drawFocusOnTop () { return onDrawFocusOnTop (); }
bool JavaScriptDrawableControl::drawFocusOnTop ()
{
if (wantsFocus ())
return onDrawFocusOnTop ();
return false;
}

//------------------------------------------------------------------------
bool JavaScriptDrawableControl::getFocusPath (CGraphicsPath& outPath)
{
return onGetFocusPath (outPath, getFrame ()->getFocusWidth (), getViewSize ());
if (wantsFocus ())
return onGetFocusPath (outPath, getFrame ()->getFocusWidth (), getViewSize ());
return false;
}

//------------------------------------------------------------------------
Expand Down
31 changes: 16 additions & 15 deletions vstgui/uidescription-scripting/uiscripting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,9 @@ struct ScriptContext::Impl : ViewListenerAdapter,
auto timerObj = TimerScriptObject (
fireTime->getInt (), callback->deepCopy (), [this, context] (auto callback) {
using namespace ScriptingInternal;
ScriptAddChildScoped scs (*jsContext->getRoot (), "timerContext", context);
return evalScript (callback, "timerCallback (timerContext); ",
ScriptAddChildScoped scs (*jsContext->getRoot (), "timerContext"sv,
context);
return evalScript (callback, "timerCallback (timerContext);"sv,
"timerCallback");
});
var->setReturnVar (timerObj);
Expand Down Expand Up @@ -176,19 +177,19 @@ struct ScriptContext::Impl : ViewListenerAdapter,
auto childScriptObject = viewScriptMap.find (child);
if (childScriptObject != viewScriptMap.end ())
{
ScriptAddChildScoped scs (*jsContext->getRoot (), "child",
ScriptAddChildScoped scs (*jsContext->getRoot (), "child"sv,
childScriptObject->second->getVar ());
ScriptAddChildScoped scs2 (*jsContext->getRoot (), "context", context);
evalScript (callback, "callback (child, context); ", "callback");
ScriptAddChildScoped scs2 (*jsContext->getRoot (), "context"sv, context);
evalScript (callback, "callback (child, context);"sv, "callback");
}
else
{
auto scriptObj =
addView (child, std::make_unique<ViewScriptObject> (child, this));
ScriptAddChildScoped scs (*jsContext->getRoot (), "child",
ScriptAddChildScoped scs (*jsContext->getRoot (), "child"sv,
scriptObj->getVar ());
ScriptAddChildScoped scs2 (*jsContext->getRoot (), "context", context);
evalScript (callback, "callback (child, context); ", "callback");
ScriptAddChildScoped scs2 (*jsContext->getRoot (), "context"sv, context);
evalScript (callback, "callback (child, context);"sv, "callback");
}
});
});
Expand Down Expand Up @@ -252,12 +253,12 @@ struct ScriptContext::Impl : ViewListenerAdapter,
try
{
auto result = jsContext->evaluateComplex (script);
#if 0 // DEBUG
if (result.getVar () && !result.getVar ()->isUndefined ())
{
#if DEBUG
DebugPrint ("%s\n", result.getVar ()->getString ().data ());
#endif
}
#endif
return result.getVar ();
}
catch (const CScriptException& exc)
Expand Down Expand Up @@ -316,7 +317,7 @@ struct ScriptContext::Impl : ViewListenerAdapter,
callWhenScriptHasFunction (view, "onSizeChanged"sv, [&] (auto This, auto& obj) {
auto newSize = view->getViewSize ();
ScriptObject newSizeObject = ScriptingInternal::makeScriptRect (newSize);
ScriptAddChildScoped scs (*jsContext->getRoot (), "newSize", newSizeObject);
ScriptAddChildScoped scs (*jsContext->getRoot (), "newSize"sv, newSizeObject);
static constexpr auto script = R"(view.onSizeChanged(view, newSize);)"sv;
This->evalScript (obj->getVar (), script);
});
Expand Down Expand Up @@ -354,14 +355,14 @@ struct ScriptContext::Impl : ViewListenerAdapter,
auto childScriptObject = viewScriptMap.find (view);
if (childScriptObject != viewScriptMap.end ())
{
ScriptAddChildScoped scs (*jsContext->getRoot (), "child",
ScriptAddChildScoped scs (*jsContext->getRoot (), "child"sv,
childScriptObject->second->getVar ());
This->evalScript (obj->getVar (), script);
}
else
{
auto scriptObj = addView (view, std::make_unique<ViewScriptObject> (view, this));
ScriptAddChildScoped scs (*jsContext->getRoot (), "child", scriptObj->getVar ());
ScriptAddChildScoped scs (*jsContext->getRoot (), "child"sv, scriptObj->getVar ());
This->evalScript (obj->getVar (), script);
}
});
Expand Down Expand Up @@ -391,7 +392,7 @@ struct ScriptContext::Impl : ViewListenerAdapter,
void callEventFunction (CScriptVar* var, Event& event, std::string_view script) noexcept
{
auto scriptEvent = ScriptingInternal::makeScriptEvent (event);
ScriptAddChildScoped scs (*jsContext->getRoot (), "event", scriptEvent);
ScriptAddChildScoped scs (*jsContext->getRoot (), "event"sv, scriptEvent);
evalScript (var, script);
checkEventConsumed (scriptEvent, event);
}
Expand Down Expand Up @@ -493,7 +494,7 @@ struct ScriptContext::Impl : ViewListenerAdapter,
callWhenScriptHasFunction (control, "onValueChanged"sv, [&] (auto This, auto& obj) {
ScriptObject controlValue;
controlValue->setDouble (control->getValue ());
ScriptAddChildScoped scs (*jsContext->getRoot (), "value", controlValue);
ScriptAddChildScoped scs (*jsContext->getRoot (), "value"sv, controlValue);
static constexpr auto script = R"(view.onValueChanged(view, value);)"sv;
This->evalScript (obj->getVar (), script);
});
Expand Down
37 changes: 37 additions & 0 deletions vstgui/uidescription-scripting/uiscripting.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,43 @@ The library needs to be initialized once at runtime before any UIDescription obj
This is done with a call to `VSTGUI::UIScripting::init ();`. You need to include
`"vstgui/uiscripting/uiscripting.h"` for this symbol.

The init function accepts two optional parameters. The first parameter is a callback
function that will be called whenever an exception occurs within a script, allowing you to
handle any errors or exceptions that may arise. The second parameter is also a function
that is invoked when a script is loaded, providing its name as input. This feature can be
used, for instance, to load scripts directly from your source repository instead of the
default location in the resource folder of your plug-in or application.

```cpp
UIScripting::ReadScriptContentsFunc loadScriptFromRepositoryPath = {};
#if DEBUG
// in Debug mode, we want to load the scripts from the repository instead of from the app
// resource folder as the scripts in the app resource folder are only synchronized when we build
// the app and not in-between.
loadScriptFromRepositoryPath = [] (auto filename) -> std::string {
std::filesystem::path path (__FILE__);
if (!path.empty ())
{
path = path.parent_path ().parent_path ();
path.append ("resource");
path.append ("scripts");
path.append (filename);
if (std::filesystem::exists (path))
{
std::ifstream f (path, std::ios::in | std::ios::binary);
const auto sz = std::filesystem::file_size (path);
std::string result (sz, '\0');
f.read (result.data (), sz);
return result;
}
}
return {};
};
#endif

UIScripting::init ({}, loadScriptFromRepositoryPath);
```
All scripts of one UIDescription object will be executed in the same JavaScript context. So you
can access global variables from all your scripts if needed.
Expand Down

0 comments on commit eac1ed2

Please sign in to comment.