-
Notifications
You must be signed in to change notification settings - Fork 5
/
screens.lua
509 lines (398 loc) · 15.4 KB
/
screens.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
function screen_main()
return df.global.gview.view.child
end
local function save_state()
--todo: save cursor pos
return { mode=df.global.ui.main.mode }
end
local function restore_state(state)
--todo: restore cursor pos
df.global.ui.main.mode = state.mode
end
function execute_with_main_mode(mode, fn, active_and_no_reset)
local ws = screen_main()
if active_and_no_reset and ws.child then
error(errmsg_wrongscreen(ws))
end
local state = save_state()
df.global.ui.main.mode = mode
local ok,ret = pcall(fn, ws)
if not active_and_no_reset or not ok then
restore_state(state)
end
if not ok then
error (ret)
end
return ret
end
function execute_with_selected_zone(bldid, fn)
local zone = df.building.find(bldid)
if not zone then
error('no zone with id '..tostring(bldid))
end
if df.global.ui.main.mode == df.ui_sidebar_mode.Zones and
df.global.ui_sidebar_menus.zone.selected and df.global.ui_sidebar_menus.zone.selected.id == bldid then
return fn(screen_main(), zone)
end
return execute_with_main_mode(df.ui_sidebar_mode.Zones, function(ws)
building_focus(zone, ws)
return fn(ws, zone)
end)
end
function execute_with_selected_unit(unitid, fn)
local unit = df.unit.find(unitid)
if not unit then
error('no unit with id '..tostring(unitid))
end
if df.global.ui.main.mode == df.ui_sidebar_mode.ViewUnits and
df.global.world.units.active[df.global.ui_selected_unit].id == unitid then
return fn(screen_main(), unit)
end
return execute_with_main_mode(df.ui_sidebar_mode.ViewUnits, function(ws)
unit_focus(unit, ws)
return fn(ws, unit)
end)
end
function execute_with_nobles_screen(reset, fn)
return execute_with_main_mode(df.ui_sidebar_mode.Default, function(ws)
gui.simulateInput(ws, K'D_NOBLES')
local noblesws = dfhack.gui.getCurViewscreen() --as:df.viewscreen_layer_noblelistst
--todo: check that we have switched to nobles screen
--todo: why is this here?
if reset then
noblesws.mode = df.viewscreen_layer_noblelistst.T_mode.List
noblesws.layer_objects[0].active = true
noblesws.layer_objects[0].enabled = true
noblesws.layer_objects[1].active = false
noblesws.layer_objects[1].enabled = false
end
local ok,ret = pcall(fn, noblesws)
-- nobles screen applies changes (noble replacement) only when destroyed,
-- if we don't do it now, the app will refresh and load old data
--noblesws.breakdown_level = df.interface_breakdown_types.STOPSCREEN
noblesws.parent.child = nil
noblesws:delete()
if not ok then
error (ret)
end
return ret
end)
end
function execute_with_military_screen(fn)
-- military screen commits changes (squad creation) upon destruction, so that if the app creates a squad,
-- and requests a list straight away, the screen will not have been destroyed yet, and a new screen won't
-- show changes. so if the old screen is still there, reuse it
local milws = dfhack.gui.getCurViewscreen() --as:df.viewscreen_layer_militaryst
if milws._type == df.viewscreen_layer_militaryst and milws.breakdown_level == df.interface_breakdown_types.STOPSCREEN then
local ok,ret = pcall(fn, milws)
if not ok then
error (ret)
end
return ret
end
return execute_with_main_mode(df.ui_sidebar_mode.Default, function(ws)
gui.simulateInput(ws, K'D_MILITARY')
local milws = dfhack.gui.getCurViewscreen() --as:df.viewscreen_layer_militaryst
milws.breakdown_level = df.interface_breakdown_types.STOPSCREEN
local ok,ret = pcall(fn, milws)
if not ok then
error (ret)
end
return ret
end)
end
function execute_with_units_screen(fn)
return execute_with_main_mode(df.ui_sidebar_mode.Default, function(ws)
gui.simulateInput(ws, K'D_UNITLIST')
local unitsws = dfhack.gui.getCurViewscreen() --as:df.viewscreen_unitlistst
unitsws.breakdown_level = df.interface_breakdown_types.STOPSCREEN
local ok,ret = pcall(fn, unitsws)
if not ok then
error (ret)
end
return ret
end)
end
function execute_with_jobs_screen(fn)
return execute_with_main_mode(df.ui_sidebar_mode.Default, function(ws)
gui.simulateInput(ws, K'D_JOBLIST')
local jobsws = dfhack.gui.getCurViewscreen()
jobsws.breakdown_level = df.interface_breakdown_types.STOPSCREEN
local ok,ret = pcall(fn, jobsws)
if not ok then
error (ret)
end
return ret
end)
end
status_pages = {
Overview = -1,
Animals = 0,
Kitchen = 1,
Stone = 2,
Stocks = 3,
Health = 4,
Prices = 5,
Currency = 6,
Justice = 7,
}
function execute_with_status_page(pageid, fn)
return execute_with_main_mode(df.ui_sidebar_mode.Default, function(ws)
gui.simulateInput(ws, K'D_STATUS')
local statusws = dfhack.gui.getCurViewscreen() --as:df.viewscreen_overallstatusst
if statusws._type ~= df.viewscreen_overallstatusst then
error('error switching to status screen '..tostring(statusws._type))
end
statusws.breakdown_level = df.interface_breakdown_types.STOPSCREEN
if pageid ~= -1 then
statusws.visible_pages:insert(0,pageid)
gui.simulateInput(statusws, K'SELECT')
end
local pagews = dfhack.gui.getCurViewscreen()
pagews.breakdown_level = df.interface_breakdown_types.STOPSCREEN
local ok,ret = pcall(fn, pagews)
if not ok then
error (ret)
end
return ret
end)
end
function execute_with_manager_screen(fn)
local jobsws = df.viewscreen_joblistst:new()
gui.simulateInput(jobsws, K'UNITJOB_MANAGER')
jobsws:delete()
local managerws = dfhack.gui.getCurViewscreen() --as:df.viewscreen_jobmanagementst
managerws.breakdown_level = df.interface_breakdown_types.STOPSCREEN
local ok,ret = pcall(fn, managerws)
if not ok then
error (ret)
end
return ret
end
function execute_with_manager_orders_screen(fn)
return execute_with_manager_screen(function(ws)
gui.simulateInput(ws, K'MANAGER_NEW_ORDER')
local ordersws = dfhack.gui.getCurViewscreen() --as:df.viewscreen_createquotast
ordersws.breakdown_level = df.interface_breakdown_types.STOPSCREEN
local ok,ret = pcall(fn, ordersws)
if not ok then
error (ret)
end
return ret
end)
end
function execute_with_locations_screen(fn)
return execute_with_main_mode(df.ui_sidebar_mode.Default, function(ws)
gui.simulateInput(ws, K'D_LOCATIONS')
local locsws = dfhack.gui.getCurViewscreen() --as:df.viewscreen_locationsst
locsws.breakdown_level = df.interface_breakdown_types.STOPSCREEN
local ok,ret = pcall(fn, locsws)
if not ok then
error (ret)
end
return ret
end)
end
function execute_with_world_screen(fn)
return execute_with_main_mode(df.ui_sidebar_mode.Default, function(ws)
gui.simulateInput(ws, K'D_CIVLIST')
local locsws = dfhack.gui.getCurViewscreen() --as:df.viewscreen_civlistst
locsws.breakdown_level = df.interface_breakdown_types.STOPSCREEN
local ok,ret = pcall(fn, locsws)
if not ok then
error (ret)
end
return ret
end)
end
function execute_with_petitions_screen(fn)
return execute_with_main_mode(df.ui_sidebar_mode.Default, function(ws)
gui.simulateInput(ws, K'D_PETITIONS')
local petitionsws = dfhack.gui.getCurViewscreen() --as:df.viewscreen_petitionsst
if petitionsws._type ~= df.viewscreen_petitionsst then
error(errmsg_wrongscreen(petitionsws))
end
petitionsws.breakdown_level = df.interface_breakdown_types.STOPSCREEN
local ok,ret = pcall(fn, petitionsws)
if not ok then
error (ret)
end
return ret
end)
end
function execute_with_locations_for_building(bldid, fn)
local bld = (bldid and bldid ~= -1) and df.building.find(bldid) or df.global.world.selected_building
if not bld then
error('no building/zone with id '..tostring(bldid))
end
--todo: if all rooms can now be added to locations, just check if it's a room
if bld._type ~= df.building_civzonest and
bld._type ~= df.building_bedst and
bld._type ~= df.building_tablest and
bld._type ~= df.building_display_furniturest and
bld._type ~= df.building_statuest then
error('wrong building type '..tostring(bldid)..' '..tostring(bld._type))
end
if not bld.is_room then
error('not a room '..tostring(bldid))
end
if bld._type == df.building_civzonest then --as:bld=df.building_civzonest
if not bld.zone_flags.meeting_area then
error('not a meeting area '..tostring(bld.zone_flags.whole))
end
return execute_with_selected_zone(bldid, function(ws)
gui.simulateInput(ws, K'ASSIGN_LOCATION')
local ok,ret = pcall(fn, ws, bld)
df.global.ui.main.mode = df.ui_sidebar_mode.Zones
if not ok then
error (ret)
end
return ret
end)
end
--todo: convert this to execute_with_selected
local ws = dfhack.gui.getCurViewscreen()
if ws._type ~= df.viewscreen_dwarfmodest then
error(errmsg_wrongscreen(ws))
end
if df.global.ui.main.mode ~= df.ui_sidebar_mode.QueryBuilding or df.global.world.selected_building == nil then
error('no selected building')
end
gui.simulateInput(ws, K'ASSIGN_LOCATION')
local ok,ret = pcall(fn, ws, bld)
df.global.ui.main.mode = df.ui_sidebar_mode.QueryBuilding
if not ok then
error (ret)
end
return ret
end
function execute_with_job_details(bldid, idx, fn)
local ws = dfhack.gui.getCurViewscreen()
if ws._type ~= df.viewscreen_dwarfmodest then
error(errmsg_wrongscreen(ws))
end
if df.global.ui.main.mode ~= df.ui_sidebar_mode.QueryBuilding or df.global.world.selected_building == nil then
error('no selected building')
end
local bld = df.global.world.selected_building
--todo: check bld.id == bldid
if idx < 0 or idx > #bld.jobs then
error('invalid job idx '..tostring(idx))
end
df.global.ui_workshop_job_cursor = idx
gui.simulateInput(ws, K'BUILDJOB_DETAILS')
--xxx: this is (temporarily?) done in calling fns to distinguish between error and no details when needed
--[[if df.global.ui_sidebar_menus.job_details.job == nil then
error('could not transition to job detail settings')
end]]
local ok,ret = pcall(fn, ws, bld.jobs[idx])
-- if a viewscreen_image_creatorst has automatically been open, close it
local ws2 = dfhack.gui.getCurViewscreen()
if ws2._type == df.viewscreen_image_creatorst then
ws2.breakdown_level = df.interface_breakdown_types.STOPSCREEN
end
df.global.ui_sidebar_menus.job_details.job = nil
if not ok then
error (ret)
end
return ret
end
function execute_with_order_details(idx, fn)
return execute_with_manager_screen(function(ws)
--todo: check idx range
ws.sel_idx = idx
gui.simulateInput(ws, K'MANAGER_DETAILS')
local detws = dfhack.gui.getCurViewscreen()
if detws._type ~= df.viewscreen_workquota_detailsst then
error('could not switch to order details screen '..tostring(detws._type))
end
--xxx: if an order has an image detail only, the order of screens will be weird:
--xxx: manager->viewscreen_image_creatorst->viewscreen_workquota_detailsst
--xxx: let's destroy the last screen now in that case, so that we always continue
--xxx: either with a valid viewscreen_workquota_detailsst or with a viewscreen_image_creatorst
if detws.parent._type == df.viewscreen_image_creatorst then
detws = detws.parent
detws.child:delete()
detws.child = nil
end
local ok,ret = pcall(fn, detws)
detws.breakdown_level = df.interface_breakdown_types.STOPSCREEN
if not ok then
error (ret)
end
return ret
end)
end
function execute_with_order_conditions(idx, fn)
return execute_with_manager_screen(function(ws)
--todo: check idx range
ws.sel_idx = idx
gui.simulateInput(ws, K'MANAGER_CONDITIONS')
local condws = dfhack.gui.getCurViewscreen() --as:df.viewscreen_workquota_conditionst
if condws._type ~= df.viewscreen_workquota_conditionst then
error('could not switch to order conditions screen '..tostring(condws._type))
end
local ok,ret = pcall(fn, condws)
condws.breakdown_level = df.interface_breakdown_types.STOPSCREEN
if not ok then
error (ret)
end
return ret
end)
end
function execute_with_rooms_screen(fn)
return execute_with_main_mode(df.ui_sidebar_mode.Default, function(ws)
gui.simulateInput(ws, K'D_ROOMS')
local roomsws = dfhack.gui.getCurViewscreen() --as:df.viewscreen_buildinglistst
if roomsws._type ~= df.viewscreen_buildinglistst then
error(errmsg_wrongscreen(roomsws))
end
roomsws.breakdown_level = df.interface_breakdown_types.STOPSCREEN
local ok,ret = pcall(fn, roomsws)
if not ok then
error (ret)
end
return ret
end)
end
function execute_with_hauling_menu(fn, active_and_no_reset)
return execute_with_main_mode(df.ui_sidebar_mode.Default, function(ws)
gui.simulateInput(ws, K'D_HAULING')
if df.global.ui.main.mode ~= df.ui_sidebar_mode.Hauling then
error('error switching to hauling menu '..tostring(df.global.ui.main.mode))
end
local ok,ret = pcall(fn, ws)
if not ok then
error (ret)
end
return ret
end, active_and_no_reset)
end
function execute_with_display_items_for_building(bldid, fn)
local bld = (bldid and bldid ~= -1) and df.building.find(bldid) or df.global.world.selected_building
if not bld then
error('no building/zone with id '..tostring(bldid))
end
if bld._type ~= df.building_display_furniturest then
error('wrong building type '..tostring(bldid)..' '..tostring(bld._type))
end
--todo: convert this to execute_with_selected
local ws = dfhack.gui.getCurViewscreen()
if ws._type ~= df.viewscreen_dwarfmodest then
error(errmsg_wrongscreen(ws))
end
if df.global.ui.main.mode ~= df.ui_sidebar_mode.QueryBuilding or df.global.world.selected_building == nil then
error('no selected building')
end
gui.simulateInput(ws, K'BUILDJOB_DISPLAY_FURNITURE_SET')
local dispws = dfhack.gui.getCurViewscreen() --as:df.viewscreen_assign_display_itemst
if dispws._type ~= df.viewscreen_assign_display_itemst then
error('could not switch to display items screen '..tostring(dispws._type))
end
local ok,ret = pcall(fn, dispws, bld)
dispws.breakdown_level = df.interface_breakdown_types.STOPSCREEN
if not ok then
error (ret)
end
return ret
end