Refactor KeyboardComponent with constants for note and key handling
Replaced hardcoded values for octaves, keys, and dimensions with named constants for improved readability and maintainability. Simplified calculations and loops using these constants. Enhanced clarity in key rendering and MIDI note calculations.
This commit is contained in:
@@ -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<Int>()
|
||||
|
||||
// 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)) {
|
||||
|
||||
Reference in New Issue
Block a user