mirai/mirai-debug/src/main/kotlin/HexDebuggerGui.kt

261 lines
6.5 KiB
Kotlin
Raw Normal View History

2019-10-26 15:51:06 +08:00
@file:Suppress("EXPERIMENTAL_API_USAGE")
import javafx.geometry.Pos
import javafx.scene.control.TextArea
import javafx.scene.control.TextField
import javafx.scene.layout.Region
import javafx.scene.paint.Color
import javafx.scene.text.FontWeight
import kotlinx.coroutines.*
import kotlinx.io.core.readUInt
2019-11-15 10:39:52 +08:00
import net.mamoe.mirai.utils.io.encodeToString
2019-10-30 23:00:29 +08:00
import net.mamoe.mirai.utils.io.hexToBytes
2019-10-26 15:51:06 +08:00
import net.mamoe.mirai.utils.io.read
2019-11-15 10:39:52 +08:00
import net.mamoe.mirai.utils.io.readUVarInt
2019-10-26 15:51:06 +08:00
import tornadofx.*
import java.awt.Toolkit
import java.awt.datatransfer.DataFlavor
/**
* How to run:
*
* `gradle run`
*/
class Application : App(HexDebuggerGui::class, Styles::class)
class Styles : Stylesheet() {
companion object {
// Define css classes
val heading by cssclass()
// Define colors
val mainColor = c("#bdbd22")
}
init {
heading {
textFill = mainColor
fontSize = 20.px
fontWeight = FontWeight.BOLD
}
button {
padding = box(vertical = 5.px, horizontal = 15.px)
fontWeight = FontWeight.BOLD
fontSize = 16.px
}
label {
padding = box(vertical = 5.px, horizontal = 15.px)
fontSize = 16.px
}
textField {
padding = box(vertical = 5.px, horizontal = 15.px)
}
textArea {
fontSize = 18.px
}
val flat = mixin {
backgroundInsets += box(0.px)
borderColor += box(Color.DARKGRAY)
}
s(button, textInput) {
+flat
}
}
}
class HexDebuggerGui : View("s") {
private lateinit var input: TextArea
private lateinit var outSize: TextField
private lateinit var outUVarInt: TextField
private lateinit var outShort: TextField
private lateinit var outUInt: TextField
2019-11-24 16:54:13 +08:00
private lateinit var outString: TextArea
2019-10-26 15:51:06 +08:00
private val clip = Toolkit.getDefaultToolkit().systemClipboard
private val clipboardContent: String?
get() {
val trans = clip.getContents(null)
if (trans?.isDataFlavorSupported(DataFlavor.stringFlavor) == true) {
return try {
trans.getTransferData(DataFlavor.stringFlavor) as String
} catch (e: Exception) {
e.printStackTrace()
null
}
}
return null
}
init {
GlobalScope.launch {
var last = clipboardContent
while (true) {
delay(100)
val current = try {
clipboardContent
} catch (e: Exception) {
e.printStackTrace()
null
}
try {
if (current != last) {
withContext(Dispatchers.Main) {
input.text = current
2019-11-15 10:39:52 +08:00
updateOutputs(
current.toString()
.replace("\n", " ")
.replace("UVarInt", "", ignoreCase = true)
.replace("[", "")
.replace("]", "")
)
2019-10-26 15:51:06 +08:00
}
}
} finally {
last = current
}
}
}
}
private fun updateOutputs(value: String) {
outUVarInt.text = runOrNull {
value.hexToBytes().read {
2019-11-15 10:39:52 +08:00
readUVarInt().toString()
2019-10-26 15:51:06 +08:00
}
}
outShort.text = runOrNull {
value.hexToBytes().read {
readShort().toString()
}
}
outUInt.text = runOrNull {
2019-10-26 15:51:06 +08:00
value.hexToBytes().read {
readUInt().toString()
2019-10-26 15:51:06 +08:00
}
}
outSize.text = runOrNull {
value.hexToBytes().size.toString()
}
outString.text = runOrNull {
2019-11-15 10:39:52 +08:00
value.hexToBytes().encodeToString()
2019-10-26 15:51:06 +08:00
}
}
override val root = hbox {
//prefWidth = 735.0
minHeight = 240.0
prefHeight = minHeight
input = textarea {
promptText = "Input"
paddingVertical = 10
prefWidth = 150.0
minWidth = 100.0
//maxWidth = 150.0
fitToHeight(this@hbox)
}
vbox(10) {
label(" => ") {
alignment = Pos.CENTER
spacing = 10.0
}
button("_") {
paddingAll = 0.0
setOnMouseClicked {
if (primaryStage.isAlwaysOnTop) {
primaryStage.isAlwaysOnTop = false
text = "_"
} else {
primaryStage.isAlwaysOnTop = true
text = ""
}
}
}
alignment = Pos.CENTER
fitToHeight(this@hbox)
}
vbox(10) {
2019-11-24 16:54:13 +08:00
paddingTop = 10
alignment = Pos.TOP_RIGHT
2019-10-26 15:51:06 +08:00
label("size")
label("UVarInt")
label("short")
label("uint")
2019-10-26 15:51:06 +08:00
label("string")
children.filterIsInstance<Region>().forEach {
it.fitToParentWidth()
}
}
vbox(20) {
alignment = Pos.CENTER_RIGHT
outSize = textfield {
promptText = "Size"
2019-10-26 15:51:06 +08:00
isEditable = false
}
outUVarInt = textfield {
promptText = "UVarInt"
isEditable = false
}
outShort = textfield {
promptText = "Short"
2019-10-26 15:51:06 +08:00
isEditable = false
}
outUInt = textfield {
promptText = "UInt"
2019-10-26 15:51:06 +08:00
isEditable = false
}
2019-11-24 16:54:13 +08:00
outString = textarea {
promptText = "String"
2019-10-26 15:51:06 +08:00
isEditable = false
2019-11-24 16:54:13 +08:00
maxWidth = 100.0
minHeight = 30.0
2019-10-26 15:51:06 +08:00
}
children.filterIsInstance<Region>().forEach {
it.fitToParentWidth()
}
}
input.textProperty().onChange {
if (it == null) {
return@onChange
}
updateOutputs(it)
}
}
}
private inline fun <T> runOrNull(block: () -> T?): T? {
return try {
block()
} catch (e: Exception) {
null
}
}