Skip to content

Commit

Permalink
UI fixes and improvements
Browse files Browse the repository at this point in the history
- Show error logs in red
- Remember window state even when hitting Cmd-Q
- Keep error status visible
  • Loading branch information
romainguy committed May 15, 2024
1 parent f1f389d commit aaedaa0
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 26 deletions.
40 changes: 28 additions & 12 deletions src/jvmMain/kotlin/dev/romainguy/kotlin/explorer/Disassembly.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@

package dev.romainguy.kotlin.explorer

import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.withStyle
import dev.romainguy.kotlin.explorer.build.ByteCodeDecompiler
import dev.romainguy.kotlin.explorer.build.DexCompiler
import dev.romainguy.kotlin.explorer.build.KotlinCompiler
Expand All @@ -39,7 +43,7 @@ private val oatDumpParser = OatDumpParser()
suspend fun buildAndRun(
toolPaths: ToolPaths,
source: String,
onLogs: (String) -> Unit,
onLogs: (AnnotatedString) -> Unit,
onStatusUpdate: (String, Float) -> Unit
) = coroutineScope {
val ui = currentCoroutineContext()
Expand All @@ -59,7 +63,7 @@ suspend fun buildAndRun(

if (kotlinc.exitCode != 0) {
withContext(ui) {
onLogs(kotlinc.output.replace(path.parent.toString() + "/", ""))
onLogs(showError(kotlinc.output.replace(path.parent.toString() + "/", "")))
updater.advance("Error compiling Kotlin", 2)
}
return@launch
Expand All @@ -73,10 +77,12 @@ suspend fun buildAndRun(
)

withContext(ui) {
onLogs(java.output)
onLogs(showLogs(java.output))
val status = if (java.exitCode != 0) "Error running code" else "Run completed"
updater.advance(status)
}

updater.addJob(launch(ui) { updater.update("Ready") })
} finally {
withContext(ui) { updater.finish() }
}
Expand All @@ -89,7 +95,7 @@ suspend fun buildAndDisassemble(
onByteCode: (CodeContent) -> Unit,
onDex: (CodeContent) -> Unit,
onOat: (CodeContent) -> Unit,
onLogs: (String) -> Unit,
onLogs: (AnnotatedString) -> Unit,
onStatusUpdate: (String, Float) -> Unit,
optimize: Boolean
) = coroutineScope {
Expand All @@ -110,7 +116,7 @@ suspend fun buildAndDisassemble(

if (kotlinc.exitCode != 0) {
updater.addJob(launch(ui) {
onLogs(kotlinc.output.replace(path.parent.toString() + "/", ""))
onLogs(showError(kotlinc.output.replace(path.parent.toString() + "/", "")))
updater.advance("Error compiling Kotlin", updater.steps)
})
return@launch
Expand All @@ -121,7 +127,7 @@ suspend fun buildAndDisassemble(
val javap = byteCodeDecompiler.decompile(directory)
withContext(ui) {
val status = if (javap.exitCode != 0) {
onLogs(javap.output)
onLogs(showError(javap.output))
"Error Disassembling Java ByteCode"
} else {
onByteCode(byteCodeParser.parse(javap.output))
Expand All @@ -137,7 +143,7 @@ suspend fun buildAndDisassemble(

if (dex.exitCode != 0) {
updater.addJob(launch(ui) {
onLogs(dex.output)
onLogs(showError(dex.output))
updater.advance("Error creating DEX", 5)
})
return@launch
Expand All @@ -150,7 +156,7 @@ suspend fun buildAndDisassemble(
val dexdump = dexCompiler.dumpDex()
withContext(ui) {
val status = if (dexdump.exitCode != 0) {
onLogs(dexdump.output)
onLogs(showError(dexdump.output))
"Error creating DEX dump"
} else {
onDex(dexDumpParser.parse(dexdump.output))
Expand All @@ -170,7 +176,7 @@ suspend fun buildAndDisassemble(

if (push.exitCode != 0) {
updater.addJob(launch(ui) {
onLogs(push.output)
onLogs(showError(push.output))
updater.advance("Error pushing code to device", 3)
})
return@launch
Expand All @@ -189,8 +195,8 @@ suspend fun buildAndDisassemble(

if (dex2oat.exitCode != 0) {
updater.addJob(launch(ui) {
onLogs(dex2oat.output)
updater.advance("Ready", 2)
onLogs(showError(dex2oat.output))
updater.advance("Error compiling OAT", 2)
})
return@launch
}
Expand All @@ -208,12 +214,14 @@ suspend fun buildAndDisassemble(
updater.addJob(launch(ui) { onOat(oatDumpParser.parse(oatdump.output)) })

val status = if (oatdump.exitCode != 0) {
onLogs(oatdump.output)
onLogs(showError(oatdump.output))
"Error creating oat dump"
} else {
"Created oat dump"
}
withContext(ui) { updater.advance(status) }

updater.addJob(launch(ui) { updater.update("Ready") })
} finally {
withContext(ui) { updater.finish() }
}
Expand All @@ -236,4 +244,12 @@ private fun cleanupClasses(directory: Path) {
.forEach { path -> path.toFile().delete() }
}

private fun showError(error: String) = buildAnnotatedString {
withStyle(SpanStyle(ErrorColor)) {
append(error)
}
}

private fun showLogs(logs: String) = AnnotatedString(logs)

internal val BuiltInKotlinClass = Regex("^(kotlin|kotlinx|java|javax|org\\.(intellij|jetbrains))\\..+")
29 changes: 17 additions & 12 deletions src/jvmMain/kotlin/dev/romainguy/kotlin/explorer/KotlinExplorer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import androidx.compose.ui.input.key.Key.Companion.O
import androidx.compose.ui.input.key.Key.Companion.P
import androidx.compose.ui.input.key.Key.Companion.R
import androidx.compose.ui.input.key.Key.Companion.S
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign.Companion.Center
import androidx.compose.ui.unit.DpSize
Expand Down Expand Up @@ -84,7 +85,7 @@ private class UiState(val explorerState: ExplorerState, window: ComposeWindow) {
var previousActiveTextArea by mutableStateOf<RSyntaxTextArea?>(null)
var status by mutableStateOf("Ready")
var progress by mutableStateOf(1f)
var logs by mutableStateOf("")
var logs by mutableStateOf(AnnotatedString(""))

val searchListener = object : SearchListener {
override fun searchEvent(e: SearchEvent?) {
Expand Down Expand Up @@ -162,7 +163,7 @@ private class UiState(val explorerState: ExplorerState, window: ComposeWindow) {
progress = newProgress
}

val onLogsUpdate: (String) -> Unit = { text ->
val onLogsUpdate: (AnnotatedString) -> Unit = { text ->
logs = text
if (text.isNotEmpty()) {
explorerState.showLogs = true
Expand Down Expand Up @@ -227,7 +228,7 @@ private fun FrameWindowScope.KotlinExplorer(
}

@Composable
private fun LogsPanel(logs: String) {
private fun LogsPanel(logs: AnnotatedString) {
Column {
Title("Logs")
SelectionContainer {
Expand Down Expand Up @@ -259,8 +260,8 @@ private fun StatusBar(status: String, progress: Float) {
if (progress < 1) {
LinearProgressIndicator(
progress = { progress },
color = Color(0xff3369d6),
trackColor = Color(0xffc4c4c4),
color = ProgressColor,
trackColor = ProgressTrackColor,
strokeCap = StrokeCap.Round
)
}
Expand Down Expand Up @@ -368,7 +369,7 @@ private fun FrameWindowScope.MainMenu(
onByteCodeUpdate: (CodeContent) -> Unit,
onDexUpdate: (CodeContent) -> Unit,
onOatUpdate: (CodeContent) -> Unit,
onLogsUpdate: (String) -> Unit,
onLogsUpdate: (AnnotatedString) -> Unit,
onStatusUpdate: (String, Float) -> Unit,
onFindClicked: () -> Unit,
onFindNextClicked: () -> Unit,
Expand Down Expand Up @@ -492,7 +493,16 @@ fun main() = application {

val explorerState = remember { ExplorerState() }

Runtime.getRuntime().addShutdownHook(Thread { explorerState.writeState() })
val windowState = rememberWindowState(
size = explorerState.getWindowSize(),
position = explorerState.getWindowPosition(),
placement = explorerState.windowPlacement,
)

Runtime.getRuntime().addShutdownHook(Thread {
explorerState.setWindowState(windowState)
explorerState.writeState()
})

val themeDefinition = if (KotlinExplorerTheme.System.isDark()) {
JewelTheme.darkThemeDefinition()
Expand All @@ -510,11 +520,6 @@ fun main() = application {
ComponentStyling.decoratedWindow(titleBarStyle = titleBarStyle),
false
) {
val windowState = rememberWindowState(
size = explorerState.getWindowSize(),
position = explorerState.getWindowPosition(),
placement = explorerState.windowPlacement,
)
DecoratedWindow(
state = windowState,
onCloseRequest = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,9 @@ class ProgressUpdater(
if (step < steps) {
Logger.warn("finish() called but progress is not yet finished: step=$step")
}
sendUpdate("Ready", steps)
}

/** Add a job that needs to be joined before finishing*/
/** Add a job that needs to be joined before finishing */
fun addJob(job: Job) {
jobs.add(job)
}
Expand Down
5 changes: 5 additions & 0 deletions src/jvmMain/kotlin/dev/romainguy/kotlin/explorer/Theme.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@

package dev.romainguy.kotlin.explorer

import androidx.compose.ui.graphics.Color
import org.jetbrains.skiko.SystemTheme

val ErrorColor = Color(0xffa04646)
val ProgressColor = Color(0xff3369d6)
val ProgressTrackColor = Color(0xffc4c4c4)

enum class KotlinExplorerTheme {
Dark, Light, System;

Expand Down

0 comments on commit aaedaa0

Please sign in to comment.