Add octave controls to KeyboardComponent

Introduced buttons to dynamically adjust the octave within the range of 0 to 8. Added new CSS classes for layout and styling of octave controls, updated component logic with range validation, and reorganized the title and octave display for improved UI.
This commit is contained in:
2025-06-06 19:32:15 +02:00
parent b48d6f3aca
commit 68a15bab8b

View File

@@ -6,8 +6,14 @@ import kotlinx.html.js.onMouseLeaveFunction
import kotlinx.html.js.onMouseUpFunction
import kotlinx.html.style
import kotlinx.html.svg
import nl.astraeus.css.properties.AlignItems
import nl.astraeus.css.properties.Display
import nl.astraeus.css.properties.FlexDirection
import nl.astraeus.css.properties.FontWeight
import nl.astraeus.css.properties.JustifyContent
import nl.astraeus.css.properties.Position
import nl.astraeus.css.properties.TextAlign
import nl.astraeus.css.properties.prc
import nl.astraeus.css.properties.px
import nl.astraeus.css.properties.rem
import nl.astraeus.css.style.cls
@@ -28,13 +34,26 @@ import org.w3c.dom.events.MouseEvent
*/
class KeyboardComponent(
val title: String = "Keyboard",
val octave: Int = 4,
initialOctave: Int = 4,
val keyboardWidth: Int = 210,
val keyboardHeight: Int = keyboardWidth / 2,
val onNoteDown: (Int) -> Unit = {},
val onNoteUp: (Int) -> Unit = {}
) : Komponent() {
// Current octave with range validation
private var _octave: Int = initialOctave
var octave: Int
get() = _octave
set(value) {
_octave = when {
value < 0 -> 0
value > 8 -> 8
else -> value
}
requestUpdate()
}
// Set to track which notes are currently pressed
private val pressedNotes = mutableSetOf<Int>()
@@ -87,14 +106,43 @@ class KeyboardComponent(
}
}
div(KeyboardTitleCls.name) {
// Show title of the keyboard
+title
}
div(KeyboardControlsCls.name) {
// Decrease octave button
div(OctaveButtonCls.name) {
style = "width: ${whiteKeyWidth}px"
+"<"
onMouseDownFunction = { event ->
if (event is MouseEvent) {
octave--
event.preventDefault()
}
}
}
div(KeyboardOctaveCls.name) {
// Show current octave the piano is being played at
+"Octave: $octave"
// Title and octave display container
div(KeyboardInfoCls.name) {
div(KeyboardTitleCls.name) {
// Show title of the keyboard
+title
}
div(KeyboardOctaveCls.name) {
// Show current octave the piano is being played at
+"Octave: $octave"
}
}
// Increase octave button
div(OctaveButtonCls.name) {
style = "width: ${whiteKeyWidth}px"
+">"
onMouseDownFunction = { event ->
if (event is MouseEvent) {
octave++
event.preventDefault()
}
}
}
}
div(KeyboardKeysCls.name) {
@@ -207,9 +255,12 @@ class KeyboardComponent(
companion object : CssId("keyboard") {
object KeyboardCls : CssName()
object KeyboardControlsCls : CssName()
object KeyboardInfoCls : CssName()
object KeyboardTitleCls : CssName()
object KeyboardOctaveCls : CssName()
object KeyboardKeysCls : CssName()
object OctaveButtonCls : CssName()
object WhiteKeyCls : CssName()
object BlackKeyCls : CssName()
@@ -219,31 +270,57 @@ class KeyboardComponent(
position(Position.relative)
margin(5.px)
select(cls(KeyboardControlsCls)) {
position(Position.relative)
display(Display.flex)
flexDirection(FlexDirection.row)
justifyContent(JustifyContent.spaceBetween)
alignItems(AlignItems.center)
width(100.prc)
height(50.px)
marginBottom(10.px)
}
select(cls(KeyboardInfoCls)) {
display(Display.flex)
flexDirection(FlexDirection.column)
alignItems(AlignItems.center)
justifyContent(JustifyContent.center)
flex("1")
}
select(cls(KeyboardTitleCls)) {
position(Position.absolute)
width(100.px)
textAlign(TextAlign.center)
fontSize(1.2.rem)
color(Css.currentStyle.mainFontColor)
top(5.px)
left(0.px)
right(0.px)
}
select(cls(KeyboardOctaveCls)) {
position(Position.absolute)
width(100.px)
textAlign(TextAlign.center)
fontSize(1.0.rem)
color(Css.currentStyle.mainFontColor)
top(30.px)
left(0.px)
right(0.px)
marginTop(5.px)
}
select(cls(OctaveButtonCls)) {
height(50.px)
plain("background-color", Css.currentStyle.buttonBackgroundColor.toString())
color(Css.currentStyle.mainFontColor)
border("1px solid ${Css.currentStyle.buttonBorderColor}")
textAlign(TextAlign.center)
lineHeight(50.px)
fontSize(1.5.rem)
fontWeight(FontWeight.bold)
cursor("pointer")
plain("-webkit-touch-callout", "none")
plain("-webkit-user-select", "none")
plain("-moz-user-select", "none")
plain("-ms-user-select", "none")
plain("user-select", "none")
}
select(cls(KeyboardKeysCls)) {
position(Position.absolute)
top(60.px)
position(Position.relative)
}
}