Move stuff in base
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
package nl.astraeus.vst.ui.components
|
||||
|
||||
import kotlinx.html.classes
|
||||
import kotlinx.html.js.onMouseWheelFunction
|
||||
import kotlinx.html.js.onWheelFunction
|
||||
import kotlinx.html.org.w3c.dom.events.Event
|
||||
import kotlinx.html.span
|
||||
import kotlinx.html.style
|
||||
import kotlinx.html.svg
|
||||
import nl.astraeus.css.properties.*
|
||||
import nl.astraeus.css.properties.Color
|
||||
import nl.astraeus.css.properties.Position
|
||||
import nl.astraeus.css.properties.TextAlign
|
||||
import nl.astraeus.css.properties.em
|
||||
import nl.astraeus.css.properties.prc
|
||||
import nl.astraeus.css.properties.px
|
||||
import nl.astraeus.css.style.cls
|
||||
import nl.astraeus.komp.HtmlBuilder
|
||||
import nl.astraeus.komp.Komponent
|
||||
@@ -14,9 +20,9 @@ import nl.astraeus.vst.ui.css.Css
|
||||
import nl.astraeus.vst.ui.css.Css.defineCss
|
||||
import nl.astraeus.vst.ui.css.CssId
|
||||
import nl.astraeus.vst.ui.css.CssName
|
||||
import nl.astraeus.vst.util.arc
|
||||
import nl.astraeus.vst.util.height
|
||||
import nl.astraeus.vst.util.width
|
||||
import nl.astraeus.vst.ui.util.arc
|
||||
import nl.astraeus.vst.ui.util.height
|
||||
import nl.astraeus.vst.ui.util.width
|
||||
import org.w3c.dom.events.MouseEvent
|
||||
import org.w3c.dom.events.WheelEvent
|
||||
import kotlin.math.PI
|
||||
@@ -77,10 +83,12 @@ open class BaseKnobComponent(
|
||||
width(width)
|
||||
height(height)
|
||||
|
||||
val actToVal = actualToValue(actualValue)
|
||||
console.log("actualValue", actualValue, "actToVal", actToVal)
|
||||
val middle = (
|
||||
((ANGLE_RANGE_DEG.toFloat() *
|
||||
(actualValue - actualMinimumValue)) /
|
||||
(actualMaximumValue - actualMinimumValue)
|
||||
(actToVal - minValue)) /
|
||||
(maxValue - minValue)
|
||||
+ START_ANGLE_DEG.toFloat()).toInt()
|
||||
)
|
||||
|
||||
@@ -143,28 +151,7 @@ open class BaseKnobComponent(
|
||||
+renderedValue
|
||||
}
|
||||
|
||||
onMouseWheelFunction = {
|
||||
if (it is WheelEvent) {
|
||||
val delta = if (it.deltaY > 0) {
|
||||
1.0
|
||||
} else {
|
||||
-1.0
|
||||
} //it.deltaY / 250.0
|
||||
|
||||
var newValue = actualValue - delta * step
|
||||
|
||||
newValue = min(newValue, actualMaximumValue)
|
||||
newValue = max(newValue, actualMinimumValue)
|
||||
|
||||
actualValue = newValue
|
||||
|
||||
callback(actualToValue(newValue))
|
||||
|
||||
requestUpdate()
|
||||
|
||||
it.preventDefault()
|
||||
}
|
||||
}
|
||||
onWheelFunction = ::wheelFunction
|
||||
|
||||
/* onMouseDownFunction = {
|
||||
if (it is MouseEvent) {
|
||||
@@ -193,6 +180,31 @@ open class BaseKnobComponent(
|
||||
}
|
||||
}
|
||||
|
||||
private fun wheelFunction(event: Event) {
|
||||
console.log("onMouseWheelFunction", event)
|
||||
if (event is WheelEvent) {
|
||||
val delta = if (event.deltaY > 0) {
|
||||
1.0
|
||||
} else {
|
||||
-1.0
|
||||
} //it.deltaY / 250.0
|
||||
|
||||
var newValue = actualValue - delta * step
|
||||
|
||||
newValue = min(newValue, actualMaximumValue)
|
||||
newValue = max(newValue, actualMinimumValue)
|
||||
|
||||
actualValue = newValue
|
||||
|
||||
callback(actualToValue(newValue))
|
||||
|
||||
requestUpdate()
|
||||
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setValueByMouseDelta(
|
||||
it: MouseEvent,
|
||||
minValue: Double = 0.0,
|
||||
|
||||
@@ -18,7 +18,7 @@ class ExpKnobComponent(
|
||||
step: Double = 0.1,
|
||||
width: Int = 50,
|
||||
height: Int = 60,
|
||||
renderer: (Double) -> String = { nv -> formatDouble(nv, 2) },
|
||||
renderer: (Double) -> String = { nv -> formatDouble(nv, 3) },
|
||||
callback: (Double) -> Unit = {}
|
||||
) : BaseKnobComponent(
|
||||
value,
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package nl.astraeus.vst.ui.components
|
||||
|
||||
import kotlinx.html.div
|
||||
import nl.astraeus.komp.HtmlBuilder
|
||||
import nl.astraeus.komp.Komponent
|
||||
import nl.astraeus.vst.ui.css.Css.defineCss
|
||||
import nl.astraeus.vst.ui.css.CssId
|
||||
import nl.astraeus.vst.ui.css.CssName
|
||||
|
||||
class KeyboardInputComponent : Komponent() {
|
||||
override fun HtmlBuilder.render() {
|
||||
div {
|
||||
+"Keyboard component"
|
||||
}
|
||||
}
|
||||
|
||||
companion object : CssId("keyboard-input") {
|
||||
object KeyboardInputCss : CssName
|
||||
|
||||
init {
|
||||
defineCss {
|
||||
select(KeyboardInputCss.cls()) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
158
src/jsMain/kotlin/nl/astraeus/vst/ui/util/SVGFunctions.kt
Normal file
158
src/jsMain/kotlin/nl/astraeus/vst/ui/util/SVGFunctions.kt
Normal file
@@ -0,0 +1,158 @@
|
||||
package nl.astraeus.vst.ui.util
|
||||
|
||||
import kotlinx.html.SVG
|
||||
import kotlinx.html.unsafe
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
fun SVG.width(width: Int) {
|
||||
this.attributes["width"] = "$width"
|
||||
}
|
||||
|
||||
fun SVG.height(height: Int) {
|
||||
this.attributes["height"] = "$height"
|
||||
}
|
||||
|
||||
fun SVG.svgStyle(
|
||||
name: String,
|
||||
vararg props: Pair<String, String>
|
||||
) {
|
||||
val result = StringBuilder()
|
||||
result.append("<style>\n")
|
||||
result.append(name)
|
||||
result.append(" {\n")
|
||||
for (prop in props) {
|
||||
result.append(" ")
|
||||
result.append(prop.first)
|
||||
result.append(": ")
|
||||
result.append(prop.second)
|
||||
result.append(";\n")
|
||||
}
|
||||
result.append("}\n")
|
||||
result.append("</style>\n")
|
||||
unsafe {
|
||||
+ "$result"
|
||||
}
|
||||
}
|
||||
|
||||
fun SVG.rect(
|
||||
x: Int,
|
||||
y: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
rx: Int,
|
||||
cls: String
|
||||
) {
|
||||
this.unsafe {
|
||||
+ """
|
||||
<rect class="$cls" x="$x" y="$y" width="$width" height="$height" rx="$rx" />
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
|
||||
fun SVG.circle(
|
||||
x: Int,
|
||||
y: Int,
|
||||
radius: Int,
|
||||
cls: String
|
||||
) {
|
||||
this.unsafe {
|
||||
+ """
|
||||
<circle class="$cls" cx="$x" cy="$y" r="$radius" />
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
|
||||
fun SVG.control(
|
||||
pnt: Pair<Int, Int>,
|
||||
cls: String
|
||||
) {
|
||||
circle(pnt.first, pnt.second, 4, cls)
|
||||
}
|
||||
|
||||
private val Pair<Int, Int>.crds: String
|
||||
get() = "${this.first},${this.second}"
|
||||
|
||||
// https://svg-path-visualizer.netlify.app/bezier-curve/
|
||||
fun SVG.curve(
|
||||
start: Pair<Int, Int>,
|
||||
control1: Pair<Int, Int>,
|
||||
control2: Pair<Int, Int>,
|
||||
end: Pair<Int, Int>,
|
||||
smoothEnd: Pair<Int, Int>? = null,
|
||||
vararg smooth: Pair<Int,Int>,
|
||||
cls: String
|
||||
) {
|
||||
val smoothStr = StringBuilder()
|
||||
for (crd in smooth) {
|
||||
smoothStr.append("S ")
|
||||
smoothStr.append(crd.crds)
|
||||
smoothStr.append(" ")
|
||||
}
|
||||
val smoothEndStr = if (smoothEnd != null) {
|
||||
smoothEnd.crds
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
this.unsafe {
|
||||
+ """
|
||||
<path class="$cls" d="M ${start.crds} C ${control1.crds} ${control2.crds} ${end.crds} $smoothStr $smoothEndStr " />
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
this.control(start, cls = cls)
|
||||
this.control(control1, cls = cls)
|
||||
this.control(control2, cls = cls)
|
||||
this.control(end, cls = cls)
|
||||
for (sm in smooth) {
|
||||
this.control(sm, cls = cls)
|
||||
}
|
||||
if (smoothEnd != null) {
|
||||
this.control(smoothEnd, cls = cls)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
+"""<path d="${describeArc(middleX, middleY, radius, START_ANGLE_DEG, middle)}"
|
||||
fill="none" stroke="${volumeColor.value}" stroke-width="10" />"""
|
||||
*/
|
||||
fun SVG.arc(
|
||||
x: Int,
|
||||
y: Int,
|
||||
radius: Int,
|
||||
startAngle: Int,
|
||||
endAngle: Int,
|
||||
cls: String
|
||||
) {
|
||||
val start = polarToCartesian(x, y, radius, endAngle)
|
||||
val end = polarToCartesian(x, y, radius, startAngle)
|
||||
|
||||
val largeArcFlag = if (endAngle - startAngle <= 180) {
|
||||
"0"
|
||||
} else {
|
||||
"1"
|
||||
}
|
||||
|
||||
unsafe {
|
||||
+"""<path class="$cls"
|
||||
d="M ${start.first} ${start.second}
|
||||
A $radius $radius 0 $largeArcFlag 0 ${end.first} ${end.second}" />"""
|
||||
}
|
||||
}
|
||||
|
||||
private fun polarToCartesian(
|
||||
centerX: Int,
|
||||
centerY: Int,
|
||||
radius: Int,
|
||||
angleInDegrees: Int
|
||||
): Pair<Double, Double> {
|
||||
val angleInRadians = (angleInDegrees - 90).toDouble() * PI / 180.0
|
||||
|
||||
return Pair(
|
||||
centerX + (radius * cos(angleInRadians)),
|
||||
centerY + (radius * sin(angleInRadians))
|
||||
)
|
||||
}
|
||||
98
src/jsMain/kotlin/nl/astraeus/vst/ui/view/BaseVstView.kt
Normal file
98
src/jsMain/kotlin/nl/astraeus/vst/ui/view/BaseVstView.kt
Normal file
@@ -0,0 +1,98 @@
|
||||
package nl.astraeus.vst.ui.view
|
||||
|
||||
import kotlinx.html.div
|
||||
import kotlinx.html.js.onClickFunction
|
||||
import kotlinx.html.org.w3c.dom.events.Event
|
||||
import nl.astraeus.css.properties.Display
|
||||
import nl.astraeus.css.properties.FlexDirection
|
||||
import nl.astraeus.css.properties.Position
|
||||
import nl.astraeus.css.properties.Transform
|
||||
import nl.astraeus.css.properties.hsla
|
||||
import nl.astraeus.css.properties.prc
|
||||
import nl.astraeus.css.properties.px
|
||||
import nl.astraeus.css.properties.rem
|
||||
import nl.astraeus.css.properties.vh
|
||||
import nl.astraeus.css.properties.vw
|
||||
import nl.astraeus.css.style.cls
|
||||
import nl.astraeus.komp.HtmlBuilder
|
||||
import nl.astraeus.komp.Komponent
|
||||
import nl.astraeus.vst.ui.css.Css
|
||||
import nl.astraeus.vst.ui.css.Css.defineCss
|
||||
import nl.astraeus.vst.ui.css.CssId
|
||||
import nl.astraeus.vst.ui.css.CssName
|
||||
|
||||
class BaseVstView(
|
||||
val title: String,
|
||||
val vstView: Komponent,
|
||||
val audioStart: (e: Event) -> Unit
|
||||
) : Komponent() {
|
||||
var started = false
|
||||
|
||||
override fun HtmlBuilder.render() {
|
||||
div(BaseVstCss.name) {
|
||||
if (!started) {
|
||||
div(BaseVstCss.StartSplashCss.name) {
|
||||
div(BaseVstCss.StartBoxCss.name) {
|
||||
div(BaseVstCss.StartButtonCss.name) {
|
||||
+"START"
|
||||
onClickFunction = { event ->
|
||||
audioStart(event)
|
||||
started = true
|
||||
requestUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
include(vstView)
|
||||
}
|
||||
}
|
||||
|
||||
object BaseVstCss : CssId("base-vst-view") {
|
||||
object BaseVstCss : CssName
|
||||
object StartSplashCss : CssName
|
||||
object StartBoxCss : CssName
|
||||
object StartButtonCss : CssName
|
||||
|
||||
init {
|
||||
defineCss {
|
||||
select(BaseVstCss.cls()) {
|
||||
display(Display.flex)
|
||||
flexDirection(FlexDirection.column)
|
||||
}
|
||||
|
||||
select(cls(StartSplashCss)) {
|
||||
position(Position.fixed)
|
||||
left(0.px)
|
||||
top(0.px)
|
||||
width(100.vw)
|
||||
height(100.vh)
|
||||
zIndex(100)
|
||||
backgroundColor(hsla(32, 0, 5, 0.65))
|
||||
|
||||
select(cls(StartBoxCss)) {
|
||||
position(Position.relative)
|
||||
left(25.vw)
|
||||
top(25.vh)
|
||||
width(50.vw)
|
||||
height(50.vh)
|
||||
backgroundColor(hsla(239, 50, 10, 1.0))
|
||||
borderColor(Css.currentStyle.mainFontColor)
|
||||
borderWidth(2.px)
|
||||
|
||||
select(cls(StartButtonCss)) {
|
||||
position(Position.absolute)
|
||||
left(50.prc)
|
||||
top(50.prc)
|
||||
transform(Transform("translate(-50%, -50%)"))
|
||||
padding(1.rem)
|
||||
backgroundColor(Css.currentStyle.buttonBackgroundColor)
|
||||
cursor("pointer")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user