@@ -9,29 +9,38 @@ import androidx.compose.foundation.layout.fillMaxSize
9
9
import androidx.compose.foundation.layout.fillMaxWidth
10
10
import androidx.compose.foundation.layout.height
11
11
import androidx.compose.foundation.layout.padding
12
+ import androidx.compose.material3.DropdownMenu
13
+ import androidx.compose.material3.DropdownMenuItem
12
14
import androidx.compose.material3.FilledTonalButton
15
+ import androidx.compose.material3.Icon
13
16
import androidx.compose.material3.MaterialTheme
14
17
import androidx.compose.material3.Text
15
18
import androidx.compose.material3.contentColorFor
16
19
import androidx.compose.runtime.Composable
17
20
import androidx.compose.runtime.LaunchedEffect
18
21
import androidx.compose.runtime.collectAsState
19
22
import androidx.compose.runtime.getValue
23
+ import androidx.compose.runtime.mutableStateOf
20
24
import androidx.compose.runtime.remember
25
+ import androidx.compose.runtime.setValue
21
26
import androidx.compose.ui.Alignment
22
27
import androidx.compose.ui.Modifier
23
28
import androidx.compose.ui.graphics.Color
24
29
import androidx.compose.ui.unit.dp
25
30
import warlockfe.warlock3.compose.components.CompassView
26
31
import warlockfe.warlock3.compose.components.ResizablePanel
27
32
import warlockfe.warlock3.compose.components.ResizablePanelState
33
+ import warlockfe.warlock3.compose.icons.Arrow_right
28
34
import warlockfe.warlock3.compose.ui.components.HandsView
29
35
import warlockfe.warlock3.compose.ui.components.IndicatorView
30
36
import warlockfe.warlock3.compose.ui.components.VitalBars
31
37
import warlockfe.warlock3.compose.ui.window.ScrollEvent
32
38
import warlockfe.warlock3.compose.ui.window.WindowUiState
33
39
import warlockfe.warlock3.compose.ui.window.WindowView
40
+ import warlockfe.warlock3.compose.util.LocalLogger
34
41
import warlockfe.warlock3.compose.util.toColor
42
+ import warlockfe.warlock3.core.client.WarlockAction
43
+ import warlockfe.warlock3.core.client.WarlockMenuData
35
44
import warlockfe.warlock3.core.prefs.defaultStyles
36
45
import warlockfe.warlock3.core.text.StyleDefinition
37
46
import warlockfe.warlock3.core.window.WindowLocation
@@ -62,6 +71,26 @@ fun GameView(
62
71
63
72
val subWindows = viewModel.windowUiStates.collectAsState()
64
73
val mainWindow = viewModel.mainWindowUiState.collectAsState()
74
+
75
+ var openMenuId: Int? by remember { mutableStateOf(null ) }
76
+ var openMenu: WarlockMenuData ? by remember { mutableStateOf(null ) }
77
+
78
+ LaunchedEffect (openMenuId) {
79
+ if (openMenuId != null ) {
80
+ viewModel.menuData.collect { menuData ->
81
+ openMenu = menuData
82
+ }
83
+ } else {
84
+ openMenu = null
85
+ }
86
+ }
87
+
88
+ ActionContextMenu (
89
+ menuData = openMenu,
90
+ expectedMenuId = openMenuId,
91
+ onDismiss = { openMenuId = null },
92
+ )
93
+
65
94
GameTextWindows (
66
95
modifier = Modifier .fillMaxWidth().weight(1f ),
67
96
subWindowUiStates = subWindows.value,
@@ -70,8 +99,20 @@ fun GameView(
70
99
topHeight = viewModel.topHeight.collectAsState(null ).value,
71
100
leftWidth = viewModel.leftWidth.collectAsState(null ).value,
72
101
rightWidth = viewModel.rightWidth.collectAsState(null ).value,
73
- onActionClicked = {
74
- viewModel.sendCommand(it)
102
+ onActionClicked = { action ->
103
+ when (action) {
104
+ is WarlockAction .SendCommand -> {
105
+ viewModel.sendCommand(action.command)
106
+ }
107
+
108
+ is WarlockAction .OpenMenu -> {
109
+ openMenuId = action.onClick()
110
+ }
111
+
112
+ else -> {
113
+ // Not our concern
114
+ }
115
+ }
75
116
},
76
117
onMoveClicked = { name, location ->
77
118
viewModel.moveWindow(name = name, location = location)
@@ -96,6 +137,91 @@ fun GameView(
96
137
}
97
138
}
98
139
140
+ @Composable
141
+ fun ActionContextMenu (
142
+ menuData : WarlockMenuData ? ,
143
+ expectedMenuId : Int? ,
144
+ onDismiss : () -> Unit ,
145
+ ) {
146
+ val logger = LocalLogger .current
147
+ if (menuData != null ) {
148
+ if (expectedMenuId == menuData.id) {
149
+ DropdownMenu (
150
+ expanded = true ,
151
+ onDismissRequest = onDismiss,
152
+ ) {
153
+ val groups = menuData.items.groupBy { it.category.split(' -' ).first() }
154
+ val categories = groups.keys.sorted()
155
+ categories.forEach { category ->
156
+ val items = groups[category]!!
157
+ if (! category.contains(' _' )) {
158
+ items.forEach { item ->
159
+ logger.debug { " Menu item: $item " }
160
+ DropdownMenuItem (
161
+ text = {
162
+ Text (item.label)
163
+ },
164
+ onClick = item.action
165
+ )
166
+ }
167
+ } else {
168
+ var expanded by remember(category) { mutableStateOf(false ) }
169
+ DropdownMenuItem (
170
+ text = {
171
+ Text (category.split(' _' ).getOrNull(1 ) ? : " Unknown" )
172
+ },
173
+ onClick = { expanded = true },
174
+ trailingIcon = {
175
+ Icon (Arrow_right , contentDescription = " expandable" )
176
+ }
177
+ )
178
+ DropdownMenu (
179
+ expanded = expanded,
180
+ onDismissRequest = { expanded = false },
181
+ ) {
182
+ val subgroups = items.groupBy { it.category.split(' -' ).getOrNull(1 ) }
183
+ subgroups[null ]?.forEach { item ->
184
+ DropdownMenuItem (
185
+ text = {
186
+ Text (item.label)
187
+ },
188
+ onClick = item.action
189
+ )
190
+ }
191
+ val subcatories = subgroups.keys.filterNotNull().sorted()
192
+ subcatories.forEach { category ->
193
+ var expanded by remember(category) { mutableStateOf(false ) }
194
+ DropdownMenuItem (
195
+ text = {
196
+ Text (category)
197
+ },
198
+ onClick = { expanded = true },
199
+ trailingIcon = {
200
+ Icon (Arrow_right , contentDescription = " expandable" )
201
+ }
202
+ )
203
+ DropdownMenu (
204
+ expanded = expanded,
205
+ onDismissRequest = { expanded = false },
206
+ ) {
207
+ subgroups[category]?.forEach { item ->
208
+ DropdownMenuItem (
209
+ text = {
210
+ Text (item.label)
211
+ },
212
+ onClick = item.action
213
+ )
214
+ }
215
+ }
216
+ }
217
+ }
218
+ }
219
+ }
220
+ }
221
+ }
222
+ }
223
+ }
224
+
99
225
@Composable
100
226
fun GameTextWindows (
101
227
modifier : Modifier ,
@@ -105,7 +231,7 @@ fun GameTextWindows(
105
231
topHeight : Int? ,
106
232
leftWidth : Int? ,
107
233
rightWidth : Int? ,
108
- onActionClicked : (String ) -> Unit ,
234
+ onActionClicked : (WarlockAction ) -> Unit ,
109
235
onMoveClicked : (name: String , WindowLocation ) -> Unit ,
110
236
onHeightChanged : (String , Int ) -> Unit ,
111
237
onWidthChanged : (String , Int ) -> Unit ,
@@ -295,7 +421,7 @@ fun WindowViews(
295
421
windowStates : List <WindowUiState >,
296
422
selectedWindow : String ,
297
423
isHorizontal : Boolean ,
298
- onActionClicked : (String ) -> Unit ,
424
+ onActionClicked : (WarlockAction ) -> Unit ,
299
425
onMoveClicked : (String , WindowLocation ) -> Unit ,
300
426
onWidthChanged : (String , Int ) -> Unit ,
301
427
onHeightChanged : (String , Int ) -> Unit ,
0 commit comments