From 9b5805a72e7a193d128cd930a7aaa02e81a62043 Mon Sep 17 00:00:00 2001 From: scheffle Date: Sat, 19 Oct 2024 19:47:34 +0200 Subject: [PATCH] add functions for customizing focus drawing in script views --- .../resource/scripts/customslider.js | 13 ++++ .../detail/drawable.cpp | 63 +++++++++++++++++++ .../uidescription-scripting/detail/drawable.h | 7 +++ .../detail/drawcontextobject.cpp | 6 ++ .../detail/drawcontextobject.h | 1 + .../detail/viewscriptobject.h | 2 +- .../uidescription-scripting/uiscripting.cpp | 13 ++-- vstgui/uidescription-scripting/uiscripting.md | 18 ++++++ 8 files changed, 116 insertions(+), 7 deletions(-) diff --git a/vstgui/standalone/examples/standalone/resource/scripts/customslider.js b/vstgui/standalone/examples/standalone/resource/scripts/customslider.js index a3d839d4c..25f39e232 100644 --- a/vstgui/standalone/examples/standalone/resource/scripts/customslider.js +++ b/vstgui/standalone/examples/standalone/resource/scripts/customslider.js @@ -111,6 +111,19 @@ view.draw = function(context, dirtyRect) { context.drawGraphicsPath(roundRect, "stroked"); }; +view.drawFocusOnTop = function () { return false; }; + +view.getFocusPath = function (path, focusWidth) { + var bounds = view.getBounds(); + path.addRoundRect(bounds, 4); + bounds.left -= focusWidth; + bounds.right += focusWidth; + bounds.top -= focusWidth; + bounds.bottom += focusWidth; + path.addRoundRect(bounds, 4); + return true; +}; + view.onMouseDown = function(view, event) { if(!event.mouseButtons.left) return; diff --git a/vstgui/uidescription-scripting/detail/drawable.cpp b/vstgui/uidescription-scripting/detail/drawable.cpp index 5d35d8abe..b31f35c6a 100644 --- a/vstgui/uidescription-scripting/detail/drawable.cpp +++ b/vstgui/uidescription-scripting/detail/drawable.cpp @@ -4,7 +4,10 @@ #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" //------------------------------------------------------------------------ @@ -62,6 +65,48 @@ void JavaScriptDrawable::onDraw (CDrawContext* context, const CRect& rect, const //------------------------------------------------------------------------ void JavaScriptDrawable::setup (ViewScriptObject* inObject) { scriptObject = inObject; } +//------------------------------------------------------------------------ +bool JavaScriptDrawable::onDrawFocusOnTop () +{ + auto scriptContext = scriptObject->getContext (); + if (!scriptContext) + return false; + + auto scriptRoot = scriptContext->getRoot (); + ScriptAddChildScoped scs (*scriptRoot, "view", *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 ()) + { + auto scriptRoot = scriptContext->getRoot (); + auto path = makeOwned (outPath); + ScriptObject focusWidthVar; + focusWidthVar->setDouble (focusWidth); + ScriptAddChildScoped scs (*scriptRoot, "view", *scriptObject); + ScriptAddChildScoped scs2 (*scriptRoot, "path", makeGraphicsPathScriptObject (path)); + ScriptAddChildScoped scs3 (*scriptRoot, "focusWidth", 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; +} + //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ @@ -70,6 +115,15 @@ void JavaScriptDrawableView::drawRect (CDrawContext* context, const CRect& rect) onDraw (context, rect, getViewSize ()); } +//------------------------------------------------------------------------ +bool JavaScriptDrawableView::drawFocusOnTop () { return onDrawFocusOnTop (); } + +//------------------------------------------------------------------------ +bool JavaScriptDrawableView::getFocusPath (CGraphicsPath& outPath) +{ + return onGetFocusPath (outPath, getFrame ()->getFocusWidth (), getViewSize ()); +} + //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ @@ -81,6 +135,15 @@ void JavaScriptDrawableControl::drawRect (CDrawContext* context, const CRect& re onDraw (context, rect, getViewSize ()); } +//------------------------------------------------------------------------ +bool JavaScriptDrawableControl::drawFocusOnTop () { return onDrawFocusOnTop (); } + +//------------------------------------------------------------------------ +bool JavaScriptDrawableControl::getFocusPath (CGraphicsPath& outPath) +{ + return onGetFocusPath (outPath, getFrame ()->getFocusWidth (), getViewSize ()); +} + //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ diff --git a/vstgui/uidescription-scripting/detail/drawable.h b/vstgui/uidescription-scripting/detail/drawable.h index c45b66b42..f562dec0f 100644 --- a/vstgui/uidescription-scripting/detail/drawable.h +++ b/vstgui/uidescription-scripting/detail/drawable.h @@ -18,6 +18,8 @@ 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); @@ -28,11 +30,14 @@ struct JavaScriptDrawable //------------------------------------------------------------------------ struct JavaScriptDrawableView : CView, + IFocusDrawing, JavaScriptDrawable { using CView::CView; void drawRect (CDrawContext* context, const CRect& rect) override; + bool drawFocusOnTop () override; + bool getFocusPath (CGraphicsPath& outPath) override; }; //------------------------------------------------------------------------ @@ -43,6 +48,8 @@ struct JavaScriptDrawableControl : 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); }; diff --git a/vstgui/uidescription-scripting/detail/drawcontextobject.cpp b/vstgui/uidescription-scripting/detail/drawcontextobject.cpp index b4ce480b3..2bde35445 100644 --- a/vstgui/uidescription-scripting/detail/drawcontextobject.cpp +++ b/vstgui/uidescription-scripting/detail/drawcontextobject.cpp @@ -401,6 +401,12 @@ struct GraphicsPathScriptObject : ScriptObject } }; +//------------------------------------------------------------------------ +ScriptObject makeGraphicsPathScriptObject (const SharedPointer& p) +{ + return GraphicsPathScriptObject (p); +} + //------------------------------------------------------------------------ struct DrawContextObject::Impl { diff --git a/vstgui/uidescription-scripting/detail/drawcontextobject.h b/vstgui/uidescription-scripting/detail/drawcontextobject.h index a9196b5e5..a43f14061 100644 --- a/vstgui/uidescription-scripting/detail/drawcontextobject.h +++ b/vstgui/uidescription-scripting/detail/drawcontextobject.h @@ -13,6 +13,7 @@ namespace VSTGUI { namespace ScriptingInternal { TJS::CScriptVar* makeTransformMatrixObject (); +ScriptObject makeGraphicsPathScriptObject (const SharedPointer& p); //------------------------------------------------------------------------ struct DrawContextObject : ScriptObject, diff --git a/vstgui/uidescription-scripting/detail/viewscriptobject.h b/vstgui/uidescription-scripting/detail/viewscriptobject.h index 917d3a8b0..060aa5437 100644 --- a/vstgui/uidescription-scripting/detail/viewscriptobject.h +++ b/vstgui/uidescription-scripting/detail/viewscriptobject.h @@ -42,7 +42,7 @@ struct IViewScriptObjectContext virtual IUIDescription* getUIDescription () const = 0; virtual ViewScriptObject* addView (CView* view) = 0; virtual ViewScriptMap::iterator removeView (CView* view) = 0; - virtual bool evalScript (std::string_view script) noexcept = 0; + virtual ScriptObject evalScript (std::string_view script) noexcept = 0; virtual TJS::CScriptVar* getRoot () const = 0; }; diff --git a/vstgui/uidescription-scripting/uiscripting.cpp b/vstgui/uidescription-scripting/uiscripting.cpp index 19faedb1e..f9509c810 100644 --- a/vstgui/uidescription-scripting/uiscripting.cpp +++ b/vstgui/uidescription-scripting/uiscripting.cpp @@ -247,7 +247,7 @@ struct ScriptContext::Impl : ViewListenerAdapter, control->unregisterControlListener (this); } - bool evalScript (std::string_view script) noexcept override + ScriptObject evalScript (std::string_view script) noexcept override { try { @@ -258,6 +258,7 @@ struct ScriptContext::Impl : ViewListenerAdapter, DebugPrint ("%s\n", result.getVar ()->getString ().data ()); #endif } + return result.getVar (); } catch (const CScriptException& exc) { @@ -266,16 +267,16 @@ struct ScriptContext::Impl : ViewListenerAdapter, #endif if (onScriptException) onScriptException (exc.text); - return false; + return {}; } - return true; + return {}; } - bool evalScript (CScriptVar* object, std::string_view script, - const std::string& objectName = "view") noexcept + ScriptObject evalScript (CScriptVar* object, std::string_view script, + const std::string& objectName = "view") noexcept { if (!object || script.empty ()) - return false; + return {}; vstgui_assert (object->getRefs () > 0); object->addRef (); ScriptAddChildScoped scs (*jsContext->getRoot (), objectName, object); diff --git a/vstgui/uidescription-scripting/uiscripting.md b/vstgui/uidescription-scripting/uiscripting.md index b14f8ce1a..158a398a2 100644 --- a/vstgui/uidescription-scripting/uiscripting.md +++ b/vstgui/uidescription-scripting/uiscripting.md @@ -68,6 +68,24 @@ view.draw = function(drawContext, dirtyRect) { The [drawContext](#the-drawcontext-object) parameter is the object where you call its method to draw things into the view and the dirtyRect parameter contains the rectangle that needs to be drawn. +Additionally the following two functions can be implemented to provide custom focus drawing: +```js +view.drawFocusOnTop = function () { return false; }; + +view.getFocusPath = function(path, focusWidth) { + var bounds = view.getBounds(); + path.addRoundRect (bounds, 4); + bounds.left -= focusWidth; + bounds.right += focusWidth; + bounds.top -= focusWidth; + bounds.bottom += focusWidth; + path.addRoundRect (bounds, 4); + return true; +}; +``` + +See the C++ IFocusDrawing interface for a description of these methods. + ### The JavaScriptDrawableControl You can add a `JavaScriptDrawableControl` from the view types to your view hierarchy to create a