From 218b4957821f45cc6b5c26b125d1a1124f02f8c7 Mon Sep 17 00:00:00 2001 From: scheffle Date: Sun, 15 Sep 2024 22:14:11 +0200 Subject: [PATCH] move some more complex scripts out of the uidesc file --- .../examples/standalone/CMakeLists.txt | 1 + .../resource/scripts/customslider.js | 189 ++++++++++++++++++ .../standalone/resource/scripts/hoveranim.js | 112 +++++++++-- .../examples/standalone/resource/test.uidesc | 4 +- 4 files changed, 284 insertions(+), 22 deletions(-) create mode 100644 vstgui/standalone/examples/standalone/resource/scripts/customslider.js diff --git a/vstgui/standalone/examples/standalone/CMakeLists.txt b/vstgui/standalone/examples/standalone/CMakeLists.txt index ff90eeefd..55b479c9f 100644 --- a/vstgui/standalone/examples/standalone/CMakeLists.txt +++ b/vstgui/standalone/examples/standalone/CMakeLists.txt @@ -32,6 +32,7 @@ set(standalone_font set(standalone_scripts "resource/scripts/changecoloronfocus.js" + "resource/scripts/customslider.js" "resource/scripts/hoveranim.js" "resource/scripts/test.js" "resource/scripts/viewcontainertest.js" diff --git a/vstgui/standalone/examples/standalone/resource/scripts/customslider.js b/vstgui/standalone/examples/standalone/resource/scripts/customslider.js new file mode 100644 index 000000000..a3d839d4c --- /dev/null +++ b/vstgui/standalone/examples/standalone/resource/scripts/customslider.js @@ -0,0 +1,189 @@ +view.data = { + backColor: "control.back", + frameColor: "control.frame", + valueColor: "control.value", + valueFrameColor: "control.valueframe", + lineColor: "control.line", + isVertical: false, + handleWidth: 10, + handleRange: 0, + handleRect: {}, + numLines: 9, + lineInset: 3, + secondLineInset: 3, + mouseDownStart: {x: -1, y: -1}, +}; + +view.onSizeChanged = function(view, newRect) { + bounds = view.getBounds (); + view.data.handleRect = bounds; + view.data.handleRect.left += 2; + view.data.handleRect.right -= 2; + view.data.handleRect.top += 2; + view.data.handleRect.bottom -= 2; + var width = bounds.getWidth(); + var height = bounds.getHeight(); + view.data.isVertical = width < height; + if(view.data.isVertical) + { + view.data.handleRect.bottom = view.data.handleRect.top + view.data.handleWidth; + view.data.handleRange = height - view.data.handleWidth; + } + else + { + view.data.handleRect.right = view.data.handleRect.left + view.data.handleWidth; + view.data.handleRange = width - view.data.handleWidth; + } +}; + +view.getHandleRect = function() { + var handle = view.data.handleRect.clone(); + var offset = view.data.handleRange * view.getValue(); + if(view.data.isVertical) + { + handle.top += offset; + handle.bottom += offset; + } + else + { + handle.left += offset; + handle.right += offset; + } + return handle; +}; + +view.draw = function(context, dirtyRect) { + var bounds = view.getBounds(); + + roundRect = context.createRoundGraphicsPath(bounds, 4); + + context.setFillColor(view.data.backColor); + context.setFrameColor(view.data.frameColor); + context.setLineWidth(1); + context.drawGraphicsPath(roundRect, "filled"); + context.drawGraphicsPath(roundRect, "stroked"); + + context.setFrameColor(view.data.lineColor); + context.setLineWidth(1); + var handle = view.getHandleRect(); + + numLines = view.data.numLines + 1; + drawOffset = view.data.handleRange / numLines; + lineInset = view.data.lineInset; + if(view.data.isVertical) + { + y = drawOffset + view.data.handleWidth / 2; + for(i = 1; i < numLines; i++) + { + start = {x: handle.left + lineInset, y: Math.round (y)}; + end = {x: handle.right - lineInset, y: Math.round (y)}; + if(!(i%2)) + { + start.x += view.data.secondLineInset; + end.x -= view.data.secondLineInset; + } + context.drawLine(start, end); + y += drawOffset; + } + } + else + { + x = drawOffset + view.data.handleWidth / 2; + for(i = 1; i < numLines; i++) + { + start = {x: Math.round (x), y: handle.top + lineInset}; + end = {x: Math.round (x), y: handle.bottom - lineInset}; + if(!(i%2)) + { + start.y += view.data.secondLineInset; + end.y -= view.data.secondLineInset; + } + context.drawLine(start, end); + x += drawOffset; + } + } + + roundRect = context.createRoundGraphicsPath(handle, 3); + context.setFillColor(view.data.valueColor); + context.setFrameColor(view.data.valueFrameColor); + context.setLineWidth(1); + context.drawGraphicsPath(roundRect, "filled"); + context.drawGraphicsPath(roundRect, "stroked"); +}; + +view.onMouseDown = function(view, event) { + if(!event.mouseButtons.left) + return; + if (event.modifiers.control) + { + // pass thru to default implementation for default handling + return; + } + view.data.mouseDownStart = event.mousePosition; + view.beginEdit(); + view.onMouseMove(view, event); + event.consumed = true; +}; + +view.onMouseUp = function(view, event) { + if(!event.mouseButtons.left || view.data.mouseDownStart.x == -1.0) + return; + view.data.mouseDownStart = {x: -1.0, y: -1.0}; + view.endEdit(); + event.consumed = true; +}; + +view.onMouseMove = function(view, event) { + if(!event.mouseButtons.left || view.data.mouseDownStart.x === -1.0) + return; + var pos; + if(view.data.isVertical) + { + event.mousePosition.y -= view.data.handleWidth / 2; + pos = 1 - (view.data.handleRange - event.mousePosition.y) / view.data.handleRange; + } + else + { + event.mousePosition.x -= view.data.handleWidth / 2; + pos = 1 - (view.data.handleRange - event.mousePosition.x) / view.data.handleRange; + } + if(pos < 0) + pos = 0; + else if(pos > 1) + pos = 1; + view.setValueNormalized(pos); + event.consumed = true; +}; + +view.onMouseWheel = function(view, event) { + if(view.data.isVertical) + { + if(event.mouseWheel.deltaY != 0) + { + if(event.mouseWheel.directionInvertedFromDevice) + event.mouseWheel.deltaY = -event.mouseWheel.deltaY; + if (event.modifiers.shift) + event.mouseWheel.deltaY = event.mouseWheel.deltaY * 0.1; + view.beginEdit(); + view.setValueNormalized(view.getValueNormalized() + event.mouseWheel.deltaY / 10); + view.endEdit(); + } + } + else + { + if(event.mouseWheel.deltaX != 0) + { + if(event.mouseWheel.directionInvertedFromDevice) + event.mouseWheel.deltaX = -event.mouseWheel.deltaX; + if (event.modifiers.shift) + event.mouseWheel.deltaX = event.mouseWheel.deltaX * 0.1; + view.beginEdit(); + view.setValueNormalized(view.getValueNormalized() + event.mouseWheel.deltaX / 10); + view.endEdit(); + } + } + event.consumed = true; +}; + +view.onSizeChanged(view, view.getBounds()); + diff --git a/vstgui/standalone/examples/standalone/resource/scripts/hoveranim.js b/vstgui/standalone/examples/standalone/resource/scripts/hoveranim.js index 40959030f..2ca4c6921 100644 --- a/vstgui/standalone/examples/standalone/resource/scripts/hoveranim.js +++ b/vstgui/standalone/examples/standalone/resource/scripts/hoveranim.js @@ -1,34 +1,106 @@ -view.default_opacity = 0.5; -view.opacity = view.default_opacity; -view.opacityTimer = createTimer (view, 16, function (view) { - view.opacity += view.opacityChange; - if (view.opacityChange > 0) +// Hover Opacity Animation Script +// This example script changes the opacity of the view +// when the mouse enters or exits the view + +// option: use full opacity on focus +// when true the opacity is 1 when the view has focus, even if the mouse is outside +// otherwise the view will use the default opacity instead +view.option.use_full_opacity_on_focus = true; + +// the opacity to use when the view is not hovered by the mouse +view.option.default_opacity = 0.6; + +// the current opacity of the view is stored in view.opacity +view.opacity = view.option.default_opacity; + +// the function which is called when the timer fires (see view.opacity_timer) +view.onOpacityTimer = function(view) { + view.opacity += view.opacity_change; + if (view.opacity_change > 0) { if (view.opacity > 1) { view.opacity = 1; - view.opacityTimer.stop(); + view.opacity_timer.stop(); } } else { - if (view.opacity <= view.default_opacity) + if (view.opacity <= view.option.default_opacity) { - view.opacity = view.default_opacity; - view.opacityTimer.stop(); + view.opacity = view.option.default_opacity; + view.opacity_timer.stop(); } } view.setAttribute("opacity", view.opacity); -}); -view.setAttribute("mouse-enabled", true); -view.setAttribute("opacity", view.opacity); -view.onRemoved = function (view) { view.opacityTimer.stop(); }; -view.onMouseEnter = function (view, event) { - view.opacityChange = 0.1; - view.opacityTimer.start(); }; -view.onMouseExit = function (view, event) { - view.opacityChange = -0.05; - view.opacityTimer.start(); - event.consume = 1; + +// the timer to change the opacity is stored in view.opacity_timer +view.opacity_timer = createTimer(view, 16, view.onOpacityTimer); + +// variable to remember the state of the focus +view.has_focus = false; + +// variable to remember if the mouse is inside when the view took focus +view.mouse_inside = false; + +// we install a mouse enter listener +// when the mouse enters the view we start the opacity change timer +view.onMouseEnter = function(view, event) { + view.mouse_inside = true; + if (view.has_focus) + return; + view.opacity_change = 0.075; + view.opacity_timer.start(); + event.consume = true; +}; + +// we also install a mouse exit listener +// when the mouse exits the view we start the opacity change timer again +// now with a negative opacity_change variable so that in the timer callback +// the opacity is going back to the default opacity +view.onMouseExit = function(view, event) { + view.mouse_inside = false; + if (view.has_focus) + return; + view.opacity_change = -0.05; + view.opacity_timer.start(); + event.consumed = true; +}; + +// we also install a view removed listener so that we can cleanup and stop the timer +view.onRemoved = function(view) { + // cleanup, when the view is removed, stop the timer + view.opacity_timer.stop(); +}; + +// when the view takes focus we show the view with full opacity if the option is set +view.onTookFocus = function(view) { + if(view.option.use_full_opacity_on_focus) + { + view.has_focus = true; + view.opacity_timer.stop(); + view.setAttribute("opacity", 1); + view.opacity = 1; + } +}; + +// when the view lost focus we start the opacity animation when the mouse is not +// inside this view if the option is set +view.onLostFocus = function(view) { + if(view.option.use_full_opacity_on_focus) + { + view.has_focus = false; + if (!view.mouse_inside) + { + view.onMouseExit(view, undefind); + } + } }; + +// enable the mouse, otherwise no mouse listener is called +view.setAttribute("mouse-enabled", true); + +// set the initial view opacity +view.setAttribute("opacity", view.opacity); + diff --git a/vstgui/standalone/examples/standalone/resource/test.uidesc b/vstgui/standalone/examples/standalone/resource/test.uidesc index 7102a2e86..d8418b4da 100644 --- a/vstgui/standalone/examples/standalone/resource/test.uidesc +++ b/vstgui/standalone/examples/standalone/resource/test.uidesc @@ -202,7 +202,7 @@ "opacity": "1", "origin": "10, 200", "row-height": "16", - "script": "// Hover Opacity Animation Script\n// This example script changes the opacity of the view\n// when the mouse enters or exits the view\n\n/* the default opacity of the view is stored in view.default_opacity */\nview.default_opacity = 0.6;\n\n/* the current opacity of the view is stored in view.opacity */\nview.opacity = view.default_opacity;\n\n/* the timer to change the opacity is stored in view.opacity_timer */\nview.opacity_timer = createTimer(view, 16, function(view) {\n\tview.opacity += view.opacity_change;\n\tif (view.opacity_change > 0)\n\t{\n\t\tif (view.opacity > 1)\n\t\t{\n\t\t\tview.opacity = 1;\n\t\t\tview.opacity_timer.stop();\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (view.opacity <= view.default_opacity)\n\t\t{\n\t\t\tview.opacity = view.default_opacity;\n\t\t\tview.opacity_timer.stop();\n\t\t}\n\t}\n\tview.setAttribute(\"opacity\", view.opacity);\n});\n\n/* the view will be shown with full opacity when focused so the state of the focus is stored in view.hasFocus */\nview.has_focus = false;\n\n/* to correctly restore the hover state after focus lost, the state if the mouse is inside the view or outside \n is stored in view.mouseInside\n*/\nview.mouse_inside = false;\n\n/* we install a mouse enter listener\n when the mouse enters the view we start the opacity change timer \n*/\nview.onMouseEnter = function(view, event) {\n\tview.mouse_inside = true;\n\tif (view.has_focus)\n\t\treturn;\n\tview.opacity_change = 0.075;\n\tview.opacity_timer.start();\n\tevent.consume = true;\n};\n\n/* we also install a mouse exit listener\n when the mouse exits the view we start the opacity change timer again \n now with a negative opacity_change variable so that in the timer callback \n the opacity is going back to the default opacity \n*/\nview.onMouseExit = function(view, event) {\n\tview.mouse_inside = false;\n\tif (view.has_focus)\n\t\treturn;\n\tview.opacity_change = -0.05;\n\tview.opacity_timer.start();\n\tevent.consumed = true;\n};\n\n/* we also install a view removed listener so that we can cleanup and stop the timer */\nview.onRemoved = function(view) {\n\t// cleanup, when the view is removed, stop the timer\n\tview.opacity_timer.stop();\n};\n\n/* when the view takes focus we show the view with full opacity */\nview.onTookFocus = function(view) {\n\tview.has_focus = true;\n\tview.opacity_timer.stop();\n\tview.setAttribute(\"opacity\", 1);\n\tview.opacity = 1;\n};\n\n/* when the view lost focus we start the opacity animation when the mouse is not inside this view */\nview.onLostFocus = function(view) {\n\tview.has_focus = false;\n\tif (!view.mouse_inside)\n\t{\n\t\tview.onMouseExit(view, undefind);\n\t}\n};\n\n/* enable the mouse, otherwise no mouse listener is called */\nview.setAttribute(\"mouse-enabled\", true);\n\n/* set the initial view opacity*/\nview.setAttribute(\"opacity\", view.opacity);\n\n", + "script": "//scriptfile hoveranim.js", "size": "110, 144", "style-hover": "true", "sub-controller": "WeekdaysController", @@ -260,7 +260,7 @@ "control-tag": "Test", "opacity": "1", "origin": "40, 79", - "script": "view.data = {\n\tbackColor: \"control.back\",\n\tframeColor: \"control.frame\",\n\tvalueColor: \"control.value\",\n\tvalueFrameColor: \"control.valueframe\",\n\tlineColor: \"control.line\",\n\tisVertical: false,\n\thandleWidth: 10,\n\thandleRange: 0,\n\thandleRect: {},\n\tnumLines: 9,\n\tlineInset: 3,\n\tsecondLineInset: 3,\n\tmouseDownStart: {x: -1, y: -1},\n};\n\nview.onSizeChanged = function(view, newRect) {\n\tbounds = view.getBounds ();\n\tview.data.handleRect = bounds;\n\tview.data.handleRect.left += 2;\n\tview.data.handleRect.right -= 2;\n\tview.data.handleRect.top += 2;\n\tview.data.handleRect.bottom -= 2;\n\tvar width = bounds.getWidth();\n\tvar height = bounds.getHeight();\n\tview.data.isVertical = width < height;\n\tif(view.data.isVertical)\n\t{\n\t\tview.data.handleRect.bottom = view.data.handleRect.top + view.data.handleWidth;\n\t\tview.data.handleRange = height - view.data.handleWidth;\n\t}\n\telse\n\t{\n\t\tview.data.handleRect.right = view.data.handleRect.left + view.data.handleWidth;\n\t\tview.data.handleRange = width - view.data.handleWidth;\n\t}\n};\n\nview.getHandleRect = function() {\n\tvar handle = view.data.handleRect.clone();\n\tvar offset = view.data.handleRange * view.getValue();\n\tif(view.data.isVertical)\n\t{\n\t\thandle.top += offset;\n\t\thandle.bottom += offset;\n\t}\n\telse\n\t{\n\t\thandle.left += offset;\n\t\thandle.right += offset;\n\t}\n\treturn handle;\n};\n\nview.draw = function(context, dirtyRect) {\n\tvar bounds = view.getBounds();\n\n\troundRect = context.createRoundGraphicsPath(bounds, 4);\n\t\n\tcontext.setFillColor(view.data.backColor);\n\tcontext.setFrameColor(view.data.frameColor);\n\tcontext.setLineWidth(1);\n\tcontext.drawGraphicsPath(roundRect, \"filled\");\n\tcontext.drawGraphicsPath(roundRect, \"stroked\");\n\n\tcontext.setFrameColor(view.data.lineColor);\n\tcontext.setLineWidth(1);\n\tvar handle = view.getHandleRect();\n\n\tnumLines = view.data.numLines + 1;\n\tdrawOffset = view.data.handleRange / numLines;\n\tlineInset = view.data.lineInset;\n\tif(view.data.isVertical)\n\t{\n\t\ty = drawOffset + view.data.handleWidth / 2;\n\t\tfor(i = 1; i < numLines; i++)\n\t\t{\n\t\t\tstart = {x: handle.left + lineInset, y: Math.round (y)};\n\t\t\tend = {x: handle.right - lineInset, y: Math.round (y)};\n\t\t\tif(!(i%2))\n\t\t\t{\n\t\t\t\tstart.x += view.data.secondLineInset;\n\t\t\t\tend.x -= view.data.secondLineInset;\n\t\t\t}\n\t\t\tcontext.drawLine(start, end);\n\t\t\ty += drawOffset;\n\t\t}\n\t}\n\telse\n\t{\n\t\tx = drawOffset + view.data.handleWidth / 2;\n\t\tfor(i = 1; i < numLines; i++)\n\t\t{\n\t\t\tstart = {x: Math.round (x), y: handle.top + lineInset};\n\t\t\tend = {x: Math.round (x), y: handle.bottom - lineInset};\n\t\t\tif(!(i%2))\n\t\t\t{\n\t\t\t\tstart.y += view.data.secondLineInset;\n\t\t\t\tend.y -= view.data.secondLineInset;\n\t\t\t}\n\t\t\tcontext.drawLine(start, end);\n\t\t\tx += drawOffset;\n\t\t}\n\t}\n\n\troundRect = context.createRoundGraphicsPath(handle, 3);\n\tcontext.setFillColor(view.data.valueColor);\n\tcontext.setFrameColor(view.data.valueFrameColor);\n\tcontext.setLineWidth(1);\n\tcontext.drawGraphicsPath(roundRect, \"filled\");\n\tcontext.drawGraphicsPath(roundRect, \"stroked\");\n};\n\nview.onMouseDown = function(view, event) {\n\tif(!event.mouseButtons.left)\n\t\treturn;\n\tview.data.mouseDownStart = event.mousePosition;\n\tview.beginEdit();\n\tview.onMouseMove(view, event);\n\tevent.consumed = true;\n};\n\nview.onMouseUp = function(view, event) {\n\tif(!event.mouseButtons.left || view.data.mouseDownStart.x == -1)\n\t\treturn;\n\tview.data.mouseDownStart = {x: -1, y: -1};\n\tview.endEdit();\n\tevent.consumed = true;\n};\n\nview.onMouseMove = function(view, event) {\n\tif(!event.mouseButtons.left || view.data.mouseDownStart.x == -1)\n\t\treturn;\n\tvar pos;\n\tif(view.data.isVertical)\n\t{\n\t\tevent.mousePosition.y -= view.data.handleWidth / 2;\n\t\tpos = 1 - (view.data.handleRange - event.mousePosition.y) / view.data.handleRange;\n\t}\n\telse\n\t{\n\t\tevent.mousePosition.x -= view.data.handleWidth / 2;\n\t\tpos = 1 - (view.data.handleRange - event.mousePosition.x) / view.data.handleRange;\n\t}\n\tif(pos < 0)\n\t\tpos = 0;\n\telse if(pos > 1)\n\t\tpos = 1;\n\tview.setValueNormalized(pos);\n\tevent.consumed = true;\n};\n\nview.onMouseWheel = function(view, event) {\n\tif(view.data.isVertical)\n\t{\n\t\tif(event.mouseWheel.deltaY != 0)\n\t\t{\n\t\t\tif(event.mouseWheel.directionInvertedFromDevice)\n\t\t\t\tevent.mouseWheel.deltaY = -event.mouseWheel.deltaY;\n\t\t\tif (event.modifiers.shift)\n\t\t\t\tevent.mouseWheel.deltaY = event.mouseWheel.deltaY * 0.1;\n\t\t\tview.beginEdit();\n\t\t\tview.setValueNormalized(view.getValueNormalized() + event.mouseWheel.deltaY / 10);\n\t\t\tview.endEdit();\n\t\t}\n\t}\n\telse\n\t{\n\t\tif(event.mouseWheel.deltaX != 0)\n\t\t{\n\t\t\tif(event.mouseWheel.directionInvertedFromDevice)\n\t\t\t\tevent.mouseWheel.deltaX = -event.mouseWheel.deltaX;\n\t\t\tif (event.modifiers.shift)\n\t\t\t\tevent.mouseWheel.deltaX = event.mouseWheel.deltaX * 0.1;\n\t\t\tview.beginEdit();\n\t\t\tview.setValueNormalized(view.getValueNormalized() + event.mouseWheel.deltaX / 10);\n\t\t\tview.endEdit();\n\t\t}\n\t}\n\tevent.consumed = true;\n};\n\nview.onSizeChanged(view, view.getBounds());\n\n", + "script": "//scriptfile customslider.js", "size": "235, 22", "tooltip": "JavaScriptDrawableControl", "transparent": "false",