57
57
--
58
58
-- Note: The returned function does not return a separate body rect; subviews
59
59
-- will be able to overwrite the normal UI-drawn frame!
60
- ---@param toolbar DFLayout.Toolbar
60
+ ---@param el DFLayout.DynamicUIElement
61
61
---@param dy_fn fun(): integer
62
62
---@return function
63
- local function get_computeFrame_fn(toolbar , dy_fn)
63
+ local function get_computeFrame_fn(el , dy_fn)
64
64
return function(self, parent_rect)
65
65
local ir = gui.get_interface_rect()
66
- local frame = toolbar.frame (ir)
66
+ local frame = el.frame_fn (ir)
67
67
return gui.mkdims_wh(
68
68
ir.x1 + frame.l,
69
69
ir.y1 + frame.t + dy_fn(),
@@ -72,93 +72,182 @@ local function get_computeFrame_fn(toolbar, dy_fn)
72
72
end
73
73
end
74
74
75
- ---@param buttons DFLayout.Toolbar.NamedButtons
76
- local function buttons_string(buttons)
77
- local sorted = {}
78
- for _, button in pairs(buttons) do
79
- utils.insert_sorted(sorted, button, 'offset')
75
+ ---@param buttons DFLayout.Toolbar.Layout
76
+ local function buttons_tokens(buttons)
77
+ local sorted_buttons = {}
78
+ for button_name, button in pairs(buttons) do
79
+ utils.insert_sorted(sorted_buttons, {
80
+ name = button_name,
81
+ offset = button.offset,
82
+ width = button.width,
83
+ }, 'offset')
80
84
end
81
- -- For a one-column button, use | to indicate the button's position.
82
- -- For wider buttons, use shapes like /\ or /--\ to illustrate the
83
- -- button's position and width.
84
- local str = ''
85
- for i, o in ipairs(sorted) do
86
- if o.offset > #str then
87
- str = str .. (' '):rep(o.offset - #str)
88
- end
89
- if o.width == 1 then
90
- str = str .. '|'
91
- elseif o.width > 1 then
92
- str = str .. '/' .. ('-'):rep(o.width - 2) .. '\\'
85
+ local offset = 0
86
+ local sorted_button_names = {}
87
+ local tokens_by_name = {}
88
+ for _, button_info in ipairs(sorted_buttons) do
89
+ table.insert(sorted_button_names, button_info.name)
90
+ local token = { gap = button_info.offset - offset, width = button_info.width }
91
+ if button_info.width == 1 then
92
+ -- For a one-column button, use | to indicate the button's position.
93
+ token.text = '|'
94
+ elseif button_info.width > 1 then
95
+ -- For wider buttons, use shapes like /\ or /--\ to illustrate the
96
+ -- button's position and width.
97
+ token.text = '/' .. ('-'):rep(button_info.width - 2) .. '\\'
93
98
end
99
+ offset = button_info.offset + button_info.width
100
+ tokens_by_name[button_info.name] = token
94
101
end
95
- return str
102
+ return sorted_button_names, tokens_by_name
103
+ end
104
+
105
+ local normal_frame_style = function(...)
106
+ local style = gui.FRAME_THIN(...)
107
+ style.signature_pen = false
108
+ return style
96
109
end
97
110
111
+ local hover_frame_style = function(...)
112
+ local style = gui.FRAME_BOLD(...)
113
+ style.signature_pen = false
114
+ return style
115
+ end
116
+
117
+ ---@class ToolbarDemo.ToolbarInfo
118
+ ---@field el DFLayout.DynamicUIElement
119
+ ---@field buttons DFLayout.Toolbar.Layout
120
+ ---@field button_els table<string, DFLayout.DynamicUIElement>
121
+ ---@field demo_dy fun(): integer
122
+
98
123
---@class ToolbarDemo.attrs: widgets.Panel.attrs
99
124
---@class ToolbarDemo.attrs.partial: widgets.Panel.attrs.partial
100
- ---@class ToolbarDemo.initTable: ToolbarDemo.attrs.partial, { toolbar?: DFLayout.Toolbar, toolbar_dy?: fun(): integer }
125
+ ---@field toolbar_info? ToolbarDemo.ToolbarInfo
126
+ ---@class ToolbarDemo.initTable: ToolbarDemo.attrs.partial
101
127
---@class ToolbarDemo: widgets.Panel
102
128
---@field super widgets.Panel
103
129
---@field ATTRS ToolbarDemo.attrs|fun(attributes: ToolbarDemo.attrs.partial)
104
130
---@overload fun(init_table: ToolbarDemo.initTable): self
105
131
ToolbarDemo = defclass(ToolbarDemo, widgets.Panel)
106
132
ToolbarDemo.ATTRS{
107
- frame_style = function(...)
108
- local style = gui.FRAME_THIN(...)
109
- style.signature_pen = false
110
- return style
111
- end,
133
+ frame_style = normal_frame_style,
112
134
visible = fort_toolbars_visible,
113
135
frame_background = { ch = 32, bg = COLOR_BLACK },
114
136
}
115
137
116
138
---@param args ToolbarDemo.initTable
117
139
function ToolbarDemo:init(args)
118
140
self.label = widgets.Label{ frame = { l = 0 } }
119
- if args.toolbar and args.toolbar_dy then
120
- self:update_to_toolbar(args.toolbar, args.toolbar_dy )
141
+ if args.toolbar_info then
142
+ self:update_to_toolbar(args.toolbar_info )
121
143
end
122
144
self:addviews{ self.label }
123
145
end
124
146
125
- ---@param toolbar DFLayout.Toolbar
126
- ---@param dy fun(): integer
127
- ---@return unknown
128
- function ToolbarDemo:update_to_toolbar(toolbar, dy)
129
- -- set button representation string
130
- local text = buttons_string(toolbar.buttons)
131
- local l_inset = 0
132
- if text:sub(1, 1) == ' ' then
133
- -- don't overwrite the left border edge with a plain space
134
- l_inset = 1
135
- text = text:sub(2)
147
+ ---@param toolbar_info ToolbarDemo.ToolbarInfo
148
+ ---@return ToolbarDemo
149
+ function ToolbarDemo:update_to_toolbar(toolbar_info)
150
+ local order, named_tokens = buttons_tokens(toolbar_info.buttons)
151
+ function set_button_text(lit_button_name)
152
+ local lit = false
153
+ local tokens = {}
154
+ for _, name in ipairs(order) do
155
+ local token = copyall(named_tokens[name])
156
+ if name == lit_button_name then
157
+ lit = true
158
+ token.pen = { fg = COLOR_BLACK, bg = COLOR_BLUE }
159
+ end
160
+ table.insert(tokens, token)
161
+ end
162
+ self.label:setText(tokens)
163
+ return lit
136
164
end
137
- self.label.frame.l = l_inset
138
- self.label:setText(text )
165
+
166
+ set_button_text( )
139
167
140
168
-- track actual toolbar, but with a y offset
141
- self.computeFrame = get_computeFrame_fn(toolbar, dy)
169
+ self.computeFrame = get_computeFrame_fn(toolbar_info.el, toolbar_info.demo_dy)
170
+
171
+ self.toolbar_el = toolbar_info.el
172
+ self.button_els = toolbar_info.button_els
173
+ self.set_button_text = set_button_text
142
174
143
175
return self
144
176
end
145
177
178
+ -- capture computed locations of toolbar and buttons
179
+ function ToolbarDemo:postUpdateLayout()
180
+ local ir = gui.get_interface_rect()
181
+ local function vr(el)
182
+ local f = el.frame_fn(ir)
183
+ return gui.ViewRect{ rect = gui.mkdims_wh(ir.x1 + f.l, ir.y1 + f.t, f.w, f.h) }
184
+ end
185
+ if self.toolbar_el then
186
+ self.toolbar_vr = vr(self.toolbar_el)
187
+ end
188
+ if self.button_els then
189
+ local vrs = {}
190
+ for name, el in pairs(self.button_els) do
191
+ vrs[name] = vr(el)
192
+ end
193
+ self.toolbar_button_vrs = vrs
194
+ end
195
+ end
196
+
197
+ function ToolbarDemo:render(...)
198
+ if self.toolbar_vr then
199
+ if self:getMousePos(self.toolbar_vr) then
200
+ self.frame_style = hover_frame_style
201
+ if self.toolbar_button_vrs then
202
+ local lit = false
203
+ for button_name, button_vr in pairs(self.toolbar_button_vrs) do
204
+ if self:getMousePos(button_vr) then
205
+ if self.set_button_text(button_name) then
206
+ lit = true
207
+ break
208
+ end
209
+ end
210
+ end
211
+ if not lit then
212
+ self.set_button_text()
213
+ end
214
+ end
215
+ else
216
+ self.frame_style = normal_frame_style
217
+ self.set_button_text()
218
+ end
219
+ end
220
+ return ToolbarDemo.super.render(self, ...)
221
+ end
222
+
146
223
local left_toolbar_demo = ToolbarDemo{
147
224
frame_title = 'left toolbar',
148
- toolbar = layout.fort.toolbars.left,
149
- toolbar_dy = primary_toolbar_dy,
225
+ toolbar_info = {
226
+ el = layout.elements.fort.toolbars.left,
227
+ buttons = layout.element_layouts.fort.toolbars.left.buttons,
228
+ button_els = layout.elements.fort.toolbar_buttons.left,
229
+ demo_dy = primary_toolbar_dy,
230
+ },
150
231
}
151
232
152
233
local center_toolbar_demo = ToolbarDemo{
153
234
frame_title = 'center toolbar',
154
- toolbar = layout.fort.toolbars.center,
155
- toolbar_dy = primary_toolbar_dy,
235
+ toolbar_info = {
236
+ el = layout.elements.fort.toolbars.center,
237
+ buttons = layout.element_layouts.fort.toolbars.center.buttons,
238
+ button_els = layout.elements.fort.toolbar_buttons.center,
239
+ demo_dy = primary_toolbar_dy,
240
+ },
156
241
}
157
242
158
243
local right_toolbar_demo = ToolbarDemo{
159
244
frame_title = 'right toolbar',
160
- toolbar = layout.fort.toolbars.right,
161
- toolbar_dy = primary_toolbar_dy,
245
+ toolbar_info = {
246
+ el = layout.elements.fort.toolbars.right,
247
+ buttons = layout.element_layouts.fort.toolbars.right.buttons,
248
+ button_els = layout.elements.fort.toolbar_buttons.right,
249
+ demo_dy = primary_toolbar_dy,
250
+ }
162
251
}
163
252
164
253
local secondary_toolbar_demo = ToolbarDemo{
@@ -187,7 +276,12 @@ local function update_fort_toolbars(secondary)
187
276
local function dy()
188
277
return -layout.SECONDARY_TOOLBAR_HEIGHT
189
278
end
190
- secondary_toolbar_demo:update_to_toolbar(layout.fort.secondary_toolbars[secondary], dy)
279
+ secondary_toolbar_demo:update_to_toolbar{
280
+ el = layout.elements.fort.secondary_toolbars[secondary],
281
+ buttons = layout.element_layouts.fort.secondary_toolbars[secondary].buttons,
282
+ button_els = layout.elements.fort.secondary_toolbar_buttons[secondary],
283
+ demo_dy = dy
284
+ }
191
285
updateLayout(secondary_toolbar_demo)
192
286
secondary_visible = true
193
287
else
@@ -199,56 +293,56 @@ local function update_fort_toolbars(secondary)
199
293
updateLayout(center_toolbar_demo)
200
294
end
201
295
202
- local tool_from_designation = {
296
+ local secondary_toolbar_from_designation = {
203
297
-- df.main_designation_type.NONE -- not a tool
204
- [df.main_designation_type.DIG_DIG] = 'dig ',
205
- [df.main_designation_type.DIG_REMOVE_STAIRS_RAMPS] = 'dig ',
206
- [df.main_designation_type.DIG_STAIR_UP] = 'dig ',
207
- [df.main_designation_type.DIG_STAIR_UPDOWN] = 'dig ',
208
- [df.main_designation_type.DIG_STAIR_DOWN] = 'dig ',
209
- [df.main_designation_type.DIG_RAMP] = 'dig ',
210
- [df.main_designation_type.DIG_CHANNEL] = 'dig ',
211
- [df.main_designation_type.CHOP] = 'chop ',
212
- [df.main_designation_type.GATHER] = 'gather ',
213
- [df.main_designation_type.SMOOTH] = 'smooth ',
214
- [df.main_designation_type.TRACK] = 'smooth ',
215
- [df.main_designation_type.ENGRAVE] = 'smooth ',
216
- [df.main_designation_type.FORTIFY] = 'smooth ',
298
+ [df.main_designation_type.DIG_DIG] = 'DIG ',
299
+ [df.main_designation_type.DIG_REMOVE_STAIRS_RAMPS] = 'DIG ',
300
+ [df.main_designation_type.DIG_STAIR_UP] = 'DIG ',
301
+ [df.main_designation_type.DIG_STAIR_UPDOWN] = 'DIG ',
302
+ [df.main_designation_type.DIG_STAIR_DOWN] = 'DIG ',
303
+ [df.main_designation_type.DIG_RAMP] = 'DIG ',
304
+ [df.main_designation_type.DIG_CHANNEL] = 'DIG ',
305
+ [df.main_designation_type.CHOP] = 'CHOP ',
306
+ [df.main_designation_type.GATHER] = 'GATHER ',
307
+ [df.main_designation_type.SMOOTH] = 'SMOOTH ',
308
+ [df.main_designation_type.TRACK] = 'SMOOTH ',
309
+ [df.main_designation_type.ENGRAVE] = 'SMOOTH ',
310
+ [df.main_designation_type.FORTIFY] = 'SMOOTH ',
217
311
-- df.main_designation_type.REMOVE_CONSTRUCTION -- not used?
218
- [df.main_designation_type.CLAIM] = 'mass_designation ',
219
- [df.main_designation_type.UNCLAIM] = 'mass_designation ',
220
- [df.main_designation_type.MELT] = 'mass_designation ',
221
- [df.main_designation_type.NO_MELT] = 'mass_designation ',
222
- [df.main_designation_type.DUMP] = 'mass_designation ',
223
- [df.main_designation_type.NO_DUMP] = 'mass_designation ',
224
- [df.main_designation_type.HIDE] = 'mass_designation ',
225
- [df.main_designation_type.NO_HIDE] = 'mass_designation ',
312
+ [df.main_designation_type.CLAIM] = 'ITEM_BUILDING ',
313
+ [df.main_designation_type.UNCLAIM] = 'ITEM_BUILDING ',
314
+ [df.main_designation_type.MELT] = 'ITEM_BUILDING ',
315
+ [df.main_designation_type.NO_MELT] = 'ITEM_BUILDING ',
316
+ [df.main_designation_type.DUMP] = 'ITEM_BUILDING ',
317
+ [df.main_designation_type.NO_DUMP] = 'ITEM_BUILDING ',
318
+ [df.main_designation_type.HIDE] = 'ITEM_BUILDING ',
319
+ [df.main_designation_type.NO_HIDE] = 'ITEM_BUILDING ',
226
320
-- df.main_designation_type.TOGGLE_ENGRAVING -- not used?
227
- [df.main_designation_type.DIG_FROM_MARKER] = 'dig ',
228
- [df.main_designation_type.DIG_TO_MARKER] = 'dig ',
229
- [df.main_designation_type.CHOP_FROM_MARKER] = 'chop ',
230
- [df.main_designation_type.CHOP_TO_MARKER] = 'chop ',
231
- [df.main_designation_type.GATHER_FROM_MARKER] = 'gather ',
232
- [df.main_designation_type.GATHER_TO_MARKER] = 'gather ',
233
- [df.main_designation_type.SMOOTH_FROM_MARKER] = 'smooth ',
234
- [df.main_designation_type.SMOOTH_TO_MARKER] = 'smooth ',
235
- [df.main_designation_type.DESIGNATE_TRAFFIC_HIGH] = 'traffic ',
236
- [df.main_designation_type.DESIGNATE_TRAFFIC_NORMAL] = 'traffic ',
237
- [df.main_designation_type.DESIGNATE_TRAFFIC_LOW] = 'traffic ',
238
- [df.main_designation_type.DESIGNATE_TRAFFIC_RESTRICTED] = 'traffic ',
239
- [df.main_designation_type.ERASE] = 'erase ',
321
+ [df.main_designation_type.DIG_FROM_MARKER] = 'DIG ',
322
+ [df.main_designation_type.DIG_TO_MARKER] = 'DIG ',
323
+ [df.main_designation_type.CHOP_FROM_MARKER] = 'CHOP ',
324
+ [df.main_designation_type.CHOP_TO_MARKER] = 'CHOP ',
325
+ [df.main_designation_type.GATHER_FROM_MARKER] = 'GATHER ',
326
+ [df.main_designation_type.GATHER_TO_MARKER] = 'GATHER ',
327
+ [df.main_designation_type.SMOOTH_FROM_MARKER] = 'SMOOTH ',
328
+ [df.main_designation_type.SMOOTH_TO_MARKER] = 'SMOOTH ',
329
+ [df.main_designation_type.DESIGNATE_TRAFFIC_HIGH] = 'TRAFFIC ',
330
+ [df.main_designation_type.DESIGNATE_TRAFFIC_NORMAL] = 'TRAFFIC ',
331
+ [df.main_designation_type.DESIGNATE_TRAFFIC_LOW] = 'TRAFFIC ',
332
+ [df.main_designation_type.DESIGNATE_TRAFFIC_RESTRICTED] = 'TRAFFIC ',
333
+ [df.main_designation_type.ERASE] = 'ERASE ',
240
334
}
241
- local tool_from_bottom = {
335
+ local secondary_toolbar_from_bottom = {
242
336
-- df.main_bottom_mode_type.NONE
243
337
-- df.main_bottom_mode_type.BUILDING
244
338
-- df.main_bottom_mode_type.BUILDING_PLACEMENT
245
339
-- df.main_bottom_mode_type.BUILDING_PICK_MATERIALS
246
340
-- df.main_bottom_mode_type.ZONE
247
341
-- df.main_bottom_mode_type.ZONE_PAINT
248
- [df.main_bottom_mode_type.STOCKPILE] = 'stockpile ',
249
- [df.main_bottom_mode_type.STOCKPILE_PAINT] = 'stockpile_paint ',
342
+ [df.main_bottom_mode_type.STOCKPILE] = 'MAIN_STOCKPILE_MODE ',
343
+ [df.main_bottom_mode_type.STOCKPILE_PAINT] = 'STOCKPILE_NEW ',
250
344
-- df.main_bottom_mode_type.BURROW
251
- [df.main_bottom_mode_type.BURROW_PAINT] = 'burrow_paint'
345
+ [df.main_bottom_mode_type.BURROW_PAINT] = 'Add new burrow',
252
346
-- df.main_bottom_mode_type.HAULING
253
347
-- df.main_bottom_mode_type.ARENA_UNIT
254
348
-- df.main_bottom_mode_type.ARENA_TREE
@@ -262,11 +356,11 @@ local tool_from_bottom = {
262
356
local function active_secondary()
263
357
local designation = df.global.game.main_interface.main_designation_selected
264
358
if designation ~= df.main_designation_type.NONE then
265
- return tool_from_designation [designation]
359
+ return secondary_toolbar_from_designation [designation]
266
360
end
267
361
local bottom = df.global.game.main_interface.bottom_mode_selected
268
362
if bottom ~= df.main_bottom_mode_type.NONE then
269
- return tool_from_bottom [bottom]
363
+ return secondary_toolbar_from_bottom [bottom]
270
364
end
271
365
end
272
366
0 commit comments