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) val display = ByteArray(width * height * 4)
fun getRGB(x: Int, y: Int): Int { fun getRGB(x: Int, y: Int): Int {
return display[x * 4 + y * width * 4 + 0].toInt() + check(x in 0 until width && y in 0 until height)
display[x * 4 + y * width * 4 + 1].toInt() shl 8 +
display[x * 4 + y * width * 4 + 2].toInt() shl 16 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) { fun setRGB(x: Int, y: Int, intVal: Int) {
display[x * 4 + y * width * 4 + 0] = intVal.toByte() check(x in 0 until width && y in 0 until height)
display[x * 4 + y * width * 4 + 1] = (intVal shr 8).toByte()
display[x * 4 + y * width * 4 + 2] = (intVal shr 16).toByte() 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.div
import kotlinx.html.style import kotlinx.html.style
import mtmc.emulator.MonTanaMiniComputer import mtmc.emulator.MonTanaMiniComputer
import mtmc.view.DisplayView
import mtmc.view.MTMCView import mtmc.view.MTMCView
import nl.astraeus.komp.HtmlBuilder import nl.astraeus.komp.HtmlBuilder
import nl.astraeus.komp.Komponent import nl.astraeus.komp.Komponent
@@ -20,6 +21,7 @@ class HelloKomponent : Komponent() {
val computer = MonTanaMiniComputer() val computer = MonTanaMiniComputer()
val mainView = MTMCView(computer) val mainView = MTMCView(computer)
val display = DisplayView(computer)
fun main() { fun main() {
computer.speed = 1 // default to 1hz computer.speed = 1 // default to 1hz

View File

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

View File

@@ -1,18 +1,52 @@
package mtmc.view package mtmc.view
import kotlinx.html.canvas
import kotlinx.html.div import kotlinx.html.div
import mtmc.display
import mtmc.emulator.MonTanaMiniComputer import mtmc.emulator.MonTanaMiniComputer
import nl.astraeus.komp.HtmlBuilder import nl.astraeus.komp.HtmlBuilder
import nl.astraeus.komp.Komponent 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 val computer: MonTanaMiniComputer
) : Komponent() { ) : Komponent() {
override fun HtmlBuilder.render() { override fun HtmlBuilder.render() {
div("display") { 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 controlView = ControlView(computer)
val registerView = RegisterView(computer) val registerView = RegisterView(computer)
val memoryView = MemoryView(computer) val memoryView = MemoryView(computer)
val displayView = DisplayView(computer) val displayView = DiplayControlView(computer)
val consoleView = ConsoleView(computer) val consoleView = ConsoleView(computer)
override fun HtmlBuilder.render() { override fun HtmlBuilder.render() {

View File

@@ -116,6 +116,13 @@ table.register-table tr td.register-lights {
min-height: 480px; 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 */
.console { .console {