Add DiplayControlView for enhanced display rendering, refactor BufferedImage RGB logic, and update related components and styles

This commit is contained in:
2025-08-16 20:48:24 +02:00
parent 40baff5cb0
commit 6acf781324
8 changed files with 82 additions and 10 deletions

7
.idea/runConfigurations/MTMC_debug.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="MTMC debug" type="JavascriptDebugType" uri="http://localhost:4001/">
<method v="2">
<option name="Gradle.BeforeRunTask" enabled="true" tasks="jsBrowserDevelopmentExecutableDistribution" externalProjectPath="$PROJECT_DIR$" vmOptions="" scriptParameters="" />
</method>
</configuration>
</component>

10
.idea/runConfigurations/MainKt.xml generated Normal file
View File

@@ -0,0 +1,10 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="MainKt" type="JetRunConfigurationType" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="mtmc.MainKt" />
<module name="mtmc-web.jvmMain" />
<shortenClasspath name="NONE" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -8,15 +8,22 @@ class BufferedImage(
val display = ByteArray(width * height * 4)
fun getRGB(x: Int, y: Int): Int {
return display[x * 4 + y * width * 4 + 0].toInt() +
display[x * 4 + y * width * 4 + 1].toInt() shl 8 +
display[x * 4 + y * width * 4 + 2].toInt() shl 16
check(x in 0 until width && y in 0 until height)
val offset = (x + y * width) * 4
return display[offset + 0].toInt() +
display[offset + 1].toInt() shl 8 +
display[offset + 2].toInt() shl 16
}
fun setRGB(x: Int, y: Int, intVal: Int) {
display[x * 4 + y * width * 4 + 0] = intVal.toByte()
display[x * 4 + y * width * 4 + 1] = (intVal shr 8).toByte()
display[x * 4 + y * width * 4 + 2] = (intVal shr 16).toByte()
check(x in 0 until width && y in 0 until height)
val offset = (x + y * width) * 4
display[offset + 0] = intVal.toByte()
display[offset + 1] = (intVal shr 8).toByte()
display[offset + 2] = (intVal shr 16).toByte()
display[offset + 3] = 255.toByte()
}
}

View File

@@ -4,6 +4,7 @@ import kotlinx.browser.document
import kotlinx.html.div
import kotlinx.html.style
import mtmc.emulator.MonTanaMiniComputer
import mtmc.view.DisplayView
import mtmc.view.MTMCView
import nl.astraeus.komp.HtmlBuilder
import nl.astraeus.komp.Komponent
@@ -20,6 +21,7 @@ class HelloKomponent : Komponent() {
val computer = MonTanaMiniComputer()
val mainView = MTMCView(computer)
val display = DisplayView(computer)
fun main() {
computer.speed = 1 // default to 1hz

View File

@@ -3,6 +3,7 @@ package mtmc.view
import kotlinx.browser.window
import kotlinx.html.div
import kotlinx.html.input
import kotlinx.html.js.onClickFunction
import kotlinx.html.js.onKeyUpFunction
import kotlinx.html.span
import mtmc.emulator.MonTanaMiniComputer
@@ -19,11 +20,15 @@ class ConsoleView(
) : Komponent() {
val history: MutableList<String> = mutableListOf()
var input: String = ""
private var inputElement: HTMLInputElement? = null
override fun HtmlBuilder.render() {
div("console") {
+"Console view"
onClickFunction = {
inputElement?.focus()
}
div("console-history") {
for (line in history) {
div {
@@ -38,7 +43,7 @@ class ConsoleView(
input(classes = "console-input") {
value = input
autoFocus = true
val inputElement = currentElement() as? HTMLInputElement
inputElement = currentElement() as? HTMLInputElement
window.setTimeout({
inputElement?.focus()
}, 0)

View File

@@ -1,18 +1,52 @@
package mtmc.view
import kotlinx.html.canvas
import kotlinx.html.div
import mtmc.display
import mtmc.emulator.MonTanaMiniComputer
import nl.astraeus.komp.HtmlBuilder
import nl.astraeus.komp.Komponent
import nl.astraeus.komp.currentElement
import org.w3c.dom.CanvasRenderingContext2D
import org.w3c.dom.HTMLCanvasElement
import org.w3c.dom.ImageData
class DisplayView(
class DiplayControlView(
val computer: MonTanaMiniComputer
) : Komponent() {
override fun HtmlBuilder.render() {
div("display") {
+"Display"
include(display)
}
}
}
class DisplayView(
val computer: MonTanaMiniComputer
) : Komponent() {
var ctx: CanvasRenderingContext2D? = null
var imageData: ImageData? = null
override fun HtmlBuilder.render() {
canvas("display-canvas") {
width = "160px"
height = "144px"
val cv = currentElement() as? HTMLCanvasElement
ctx = cv?.getContext("2d")?.unsafeCast<CanvasRenderingContext2D>()
ctx?.fillStyle = "#404040"
ctx?.fillRect(0.0, 0.0, 160.0, 144.0)
imageData = ctx?.getImageData(0.0, 0.0, 160.0, 144.0)
}
}
override fun renderUpdate() {
// move data to canvas
imageData?.let { id ->
ctx?.putImageData(id, 0.0, 0.0)
}
}
}

View File

@@ -11,7 +11,7 @@ class MTMCView(
val controlView = ControlView(computer)
val registerView = RegisterView(computer)
val memoryView = MemoryView(computer)
val displayView = DisplayView(computer)
val displayView = DiplayControlView(computer)
val consoleView = ConsoleView(computer)
override fun HtmlBuilder.render() {

View File

@@ -116,6 +116,13 @@ table.register-table tr td.register-lights {
min-height: 480px;
}
.display-canvas {
width: 320px;
height: 288px;
image-rendering: pixelated; /* Keeps sharp pixels, no smoothing */
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: crisp-edges; /* Standard */
}
/* console */
.console {