diff --git a/src/jsMain/kotlin/nl/astraeus/vst/ui/components/KeyboardComponent.kt b/src/jsMain/kotlin/nl/astraeus/vst/ui/components/KeyboardComponent.kt index a7fbf85..a69b99c 100644 --- a/src/jsMain/kotlin/nl/astraeus/vst/ui/components/KeyboardComponent.kt +++ b/src/jsMain/kotlin/nl/astraeus/vst/ui/components/KeyboardComponent.kt @@ -47,8 +47,8 @@ class KeyboardComponent( get() = _octave set(value) { _octave = when { - value < 0 -> 0 - value > 9 -> 9 + value < MIN_OCTAVE -> MIN_OCTAVE + value > MAX_OCTAVE -> MAX_OCTAVE else -> value } requestUpdate() @@ -57,14 +57,14 @@ class KeyboardComponent( // Set to track which notes are currently pressed private val pressedNotes = mutableSetOf() - // MIDI note numbers for C4 to B4 (one octave) - private val whiteKeys = listOf(60, 62, 64, 65, 67, 69, 71) - private val blackKeys = listOf(61, 63, 66, 68, 70) + // MIDI note numbers for one octave + private val whiteKeys = BASE_WHITE_KEYS + private val blackKeys = BASE_BLACK_KEYS // Key dimensions - private val whiteKeyWidth = keyboardWidth / 7 - private val blackKeyWidth = (keyboardWidth / 9) - private val blackKeyHeight = keyboardHeight * 60 / 100 + private val whiteKeyWidth = keyboardWidth / WHITE_KEYS_PER_OCTAVE + private val blackKeyWidth = (keyboardWidth / BLACK_KEY_WIDTH_DIVISOR) + private val blackKeyHeight = keyboardHeight * BLACK_KEY_HEIGHT_PERCENTAGE / 100 // Calculate positions for black keys private val blackKeyPositions = listOf( @@ -97,12 +97,12 @@ class KeyboardComponent( pressedNotes.clear() } - private fun getOctaveOffset(): Int = (octave - 5) * 12 + private fun getOctaveOffset(): Int = (octave - OCTAVE_BASE) * NOTES_PER_OCTAVE private fun getMidiNoteFromMousePosition(x: Double, y: Double): Int? { // Check if click is on a black key (black keys are on top of white keys) if (y <= blackKeyHeight) { - for (j in 0 until 5) { + for (j in 0 until BLACK_KEYS_PER_OCTAVE) { if (x >= blackKeyPositions[j] && x <= blackKeyPositions[j] + blackKeyWidth) { return blackKeys[j] + getOctaveOffset() } @@ -110,13 +110,13 @@ class KeyboardComponent( // If no black key was pressed, check for white key val keyIndex = (x / whiteKeyWidth).toInt() - if (keyIndex in 0..6) { + if (keyIndex in 0 until WHITE_KEYS_PER_OCTAVE) { return whiteKeys[keyIndex] + getOctaveOffset() } } else { // If y > blackKeyHeight, it's definitely a white key val keyIndex = (x / whiteKeyWidth).toInt() - if (keyIndex in 0..6) { + if (keyIndex in 0 until WHITE_KEYS_PER_OCTAVE) { return whiteKeys[keyIndex] + getOctaveOffset() } } @@ -125,7 +125,7 @@ class KeyboardComponent( override fun HtmlBuilder.render() { div(KeyboardCls.name) { - style = "width: ${keyboardWidth}px; height: ${keyboardHeight + 60}px" + style = "width: ${keyboardWidth}px; height: ${keyboardHeight + KEYBOARD_CONTROLS_HEIGHT}px" onMouseLeaveFunction = { event -> if (event is MouseEvent) { @@ -196,7 +196,7 @@ class KeyboardComponent( } // Draw white keys - for (i in 0 until 7) { + for (i in 0 until WHITE_KEYS_PER_OCTAVE) { val midiNote = whiteKeys[i] + getOctaveOffset() val isPressed = pressedNotes.contains(midiNote) rect( @@ -210,7 +210,7 @@ class KeyboardComponent( } // Draw black keys - for (i in 0 until 5) { + for (i in 0 until BLACK_KEYS_PER_OCTAVE) { val midiNote = blackKeys[i] + getOctaveOffset() val isPressed = pressedNotes.contains(midiNote) rect( @@ -228,6 +228,7 @@ class KeyboardComponent( } companion object : CssId("keyboard") { + // CSS class names object KeyboardCls : CssName() object KeyboardControlsCls : CssName() object KeyboardInfoCls : CssName() @@ -240,6 +241,21 @@ class KeyboardComponent( object WhiteKeyPressedCls : CssName() object BlackKeyPressedCls : CssName() + // Constants + private const val OCTAVE_BASE = 5 + private const val NOTES_PER_OCTAVE = 12 + private const val BLACK_KEY_HEIGHT_PERCENTAGE = 60 + private const val MIN_OCTAVE = 0 + private const val MAX_OCTAVE = 9 + private const val WHITE_KEYS_PER_OCTAVE = 7 + private const val BLACK_KEYS_PER_OCTAVE = 5 + private const val BLACK_KEY_WIDTH_DIVISOR = 9 + private const val KEYBOARD_CONTROLS_HEIGHT = 60 + + // MIDI note numbers for C5 to B5 (one octave) + private val BASE_WHITE_KEYS = listOf(60, 62, 64, 65, 67, 69, 71) // C, D, E, F, G, A, B + private val BASE_BLACK_KEYS = listOf(61, 63, 66, 68, 70) // C#, D#, F#, G#, A# + init { defineCss { select(cls(KeyboardCls)) {