Skip to content

Commit 83d0179

Browse files
committed
GUI: json formatter
1 parent 2aeab0e commit 83d0179

File tree

4 files changed

+136
-2
lines changed

4 files changed

+136
-2
lines changed

desktop-gui/compose/src/main/kotlin/request/model.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ enum class Tools(val tool: Tools?, val cmd: String) {
1717
HtmlDown(null, "htmlDown"),
1818
Helper(null, "cHelper"),
1919
Note(null, "note"),
20-
None(null, "");
20+
Json(null, "json"),
21+
None(null, "")
2122
;
2223

2324
fun toolName() = if (this.tool == null) cmd else this.tool.cmd

desktop-gui/compose/src/main/kotlin/view/Common.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ fun readParams(tools: Tools, key: String, default: String = "") :String {
4141
if (m != null) {
4242
return m.getOrDefault(key, default)
4343
}
44-
return ""
44+
return default
4545
}
4646

4747
@Composable

desktop-gui/compose/src/main/kotlin/view/ContentView.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ fun ContentView(currentTool: Tools) {
2424
Tools.HtmlDown -> htmlDown()
2525
Tools.Note -> NoteView()
2626
Tools.C -> converts()
27+
Tools.Json -> JsonView()
2728
else -> {}
2829
}
2930
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package view
2+
3+
import androidx.compose.foundation.layout.*
4+
import androidx.compose.foundation.rememberScrollState
5+
import androidx.compose.foundation.verticalScroll
6+
import androidx.compose.material.Button
7+
import androidx.compose.material.MaterialTheme
8+
import androidx.compose.material.Text
9+
import androidx.compose.material.TextField
10+
import androidx.compose.runtime.*
11+
import androidx.compose.ui.Modifier
12+
import androidx.compose.ui.unit.dp
13+
import globalJson
14+
import kotlinx.serialization.json.JsonArray
15+
import kotlinx.serialization.json.JsonObject
16+
17+
@Composable
18+
fun JsonView() {
19+
var jsonString by remember { mutableStateOf("") }
20+
var jsonErrorMessage by remember { mutableStateOf<String?>(null) }
21+
var jsonObject by remember { mutableStateOf<JsonObject?>(null) }
22+
val isExpandedAll = mutableStateOf(false)
23+
24+
25+
Column(modifier = Modifier.padding(16.dp)) {
26+
Text("Enter JSON String:")
27+
TextField(
28+
value = jsonString,
29+
onValueChange = {
30+
jsonString = it
31+
32+
try {
33+
jsonObject = globalJson.decodeFromString(jsonString)
34+
jsonErrorMessage = null
35+
} catch (e: Exception) {
36+
jsonObject = null
37+
jsonErrorMessage = "Invalid JSON format: ${e.localizedMessage}"
38+
}
39+
},
40+
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp).height(200.dp),
41+
placeholder = { Text("Enter JSON here...") }
42+
)
43+
44+
jsonErrorMessage?.let {
45+
Text(text = it, color = MaterialTheme.colors.error)
46+
}
47+
48+
Spacer(modifier = Modifier.height(16.dp))
49+
50+
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
51+
Button(onClick = { isExpandedAll.value = true }) {
52+
Text("Expand All")
53+
}
54+
Button(onClick = { isExpandedAll.value = false }) {
55+
Text("Collapse All")
56+
}
57+
}
58+
59+
Spacer(modifier = Modifier.height(16.dp))
60+
61+
62+
jsonObject?.let {
63+
ExpandableJsonTreeView(json = it, isExpandedAll)
64+
}
65+
}
66+
}
67+
68+
@Composable
69+
fun ExpandableJsonTreeView(json: JsonObject, isExpandedAll: MutableState<Boolean>) {
70+
val scrollState = rememberScrollState()
71+
Column(modifier = Modifier.verticalScroll(scrollState)) {
72+
RenderJsonTree(json, level = 0, isExpandedAll)
73+
}
74+
}
75+
76+
@Composable
77+
fun RenderJsonTree(json: JsonObject, level: Int, isExpandedAll: MutableState<Boolean>) {
78+
json.keys.forEach {
79+
JsonTreeItem(it, json[it]!!, level, isExpandedAll)
80+
}
81+
}
82+
83+
@Composable
84+
fun JsonTreeItem(key: String, value: Any, level: Int, isExpandedAll: MutableState<Boolean>) {
85+
var isExpanded by remember { mutableStateOf(isExpandedAll.value)}
86+
val indentation = " ".repeat(level)
87+
88+
Column(modifier = Modifier.padding(start = 16.dp * level)) {
89+
if (value is JsonObject || value is JsonArray) {
90+
Row {
91+
Button(onClick = { isExpanded = !isExpanded }) {
92+
Text(text = if (isExpanded) "[-]" else "[+]")
93+
}
94+
Text(text = "$indentation$key:")
95+
}
96+
97+
if (isExpanded) {
98+
when (value) {
99+
is JsonObject -> RenderJsonTree(
100+
value,
101+
level + 1,
102+
isExpandedAll
103+
)
104+
is JsonArray -> RenderJsonArray(value, level + 1, isExpandedAll)
105+
}
106+
}
107+
} else {
108+
Row {
109+
Text(text = "$indentation$key: $value")
110+
}
111+
}
112+
}
113+
}
114+
115+
@Composable
116+
fun RenderJsonArray(array: JsonArray, level: Int, isExpandedAll: MutableState<Boolean>) {
117+
array.forEachIndexed { index, item ->
118+
val indentation = " ".repeat(level)
119+
Column(modifier = Modifier.padding(start = 16.dp * level)) {
120+
Row {
121+
Text(text = "$indentation[Index $index]: ")
122+
}
123+
124+
125+
when (item) {
126+
is JsonObject -> RenderJsonTree(item, level + 1, isExpandedAll)
127+
is JsonArray -> RenderJsonArray(item, level + 1, isExpandedAll)
128+
else -> Row { Text(text = "$indentation$item") }
129+
}
130+
}
131+
}
132+
}

0 commit comments

Comments
 (0)