@@ -132,35 +132,140 @@ local function fort_toolbars_visible()
132132 return visible () and fort_toolbars_demo .active
133133end
134134
135- FortToolbarDemoPanel = defclass (FortToolbarDemoPanel , widgets .Panel )
136- FortToolbarDemoPanel .ATTRS {
135+ local secondary_visible = false
136+
137+ local function primary_toolbar_dy ()
138+ if secondary_visible then
139+ -- When a secondary toolbar is active, move the primary demos up to let
140+ -- the secondary demo be right above the actual secondary:
141+ -- {l demo} {c demo} {r demo}
142+ -- {s demo}
143+ -- [s tool]
144+ -- [l tool] [c tool] [r tool] (bottom of UI)
145+ return - (layout .TOOLBAR_HEIGHT + 2 * layout .SECONDARY_TOOLBAR_HEIGHT )
146+ else
147+ -- Otherwise, draw primary toolbar demos right above the primary
148+ -- toolbars:
149+ -- {l demo} {c demo} {r demo}
150+ -- [l tool] [c tool] [r tool] (bottom of UI)
151+ return - layout .TOOLBAR_HEIGHT
152+ end
153+ end
154+
155+ -- Generates a `view:computeFrame()` function that tracks the placement of the
156+ -- given `toolbar`.
157+ --
158+ -- Note: The returned function does not return a separate body rect; subviews
159+ -- will be able to overwrite the normal UI-drawn frame!
160+ --- @param toolbar DFLayout.Toolbar
161+ --- @param dy_fn fun (): integer
162+ --- @return function
163+ local function get_computeFrame_fn (toolbar , dy_fn )
164+ return function (self , parent_rect )
165+ local ir = gui .get_interface_rect ()
166+ local frame = toolbar .frame (ir )
167+ return gui .mkdims_wh (
168+ ir .x1 + frame .l ,
169+ ir .y1 + frame .t + dy_fn (),
170+ frame .w ,
171+ frame .h )
172+ end
173+ end
174+
175+ --- @param buttons DFLayout.Toolbar.NamedButtons
176+ local function buttons_string (buttons )
177+ local sorted = {}
178+ for _ , button in pairs (buttons ) do
179+ utils .insert_sorted (sorted , button , ' offset' )
180+ end
181+ -- For a one-column button, use | to indicate the button's position.
182+ -- For wider buttons, use shapes like /\ or /--\ to illustrate the
183+ -- button's position and width.
184+ local str = ' '
185+ for i , o in ipairs (sorted ) do
186+ if o .offset > # str then
187+ str = str .. (' ' ):rep (o .offset - # str )
188+ end
189+ if o .width == 1 then
190+ str = str .. ' |'
191+ elseif o .width > 1 then
192+ str = str .. ' /' .. (' -' ):rep (o .width - 2 ) .. ' \\ '
193+ end
194+ end
195+ return str
196+ end
197+
198+ --- @class ToolbarDemo.attrs : widgets.Panel.attrs
199+ --- @class ToolbarDemo.attrs.partial : widgets.Panel.attrs.partial
200+ --- @class ToolbarDemo.initTable : ToolbarDemo.attrs.partial , { toolbar ?: DFLayout.Toolbar , toolbar_dy ?: fun (): integer }
201+ --- @class ToolbarDemo : widgets.Panel
202+ --- @field super widgets.Panel
203+ --- @field ATTRS ToolbarDemo.attrs | fun ( attributes : ToolbarDemo.attrs.partial )
204+ --- @overload fun ( init_table : ToolbarDemo.initTable ): self
205+ ToolbarDemo = defclass (ToolbarDemo , widgets .Panel )
206+ ToolbarDemo .ATTRS {
137207 frame_style = function (...)
138208 local style = gui .FRAME_THIN (... )
139209 style .signature_pen = false
140210 return style
141211 end ,
142- visible_override = true ,
143212 visible = fort_toolbars_visible ,
144213 frame_background = { ch = 32 , bg = COLOR_BLACK },
145214}
146215
147- local left_toolbar_demo = FortToolbarDemoPanel {
216+ --- @param args ToolbarDemo.initTable
217+ function ToolbarDemo :init (args )
218+ self .label = widgets .Label { frame = { l = 0 } }
219+ if args .toolbar and args .toolbar_dy then
220+ self :update_to_toolbar (args .toolbar , args .toolbar_dy )
221+ end
222+ self :addviews { self .label }
223+ end
224+
225+ --- @param toolbar DFLayout.Toolbar
226+ --- @param dy fun (): integer
227+ --- @return unknown
228+ function ToolbarDemo :update_to_toolbar (toolbar , dy )
229+ -- set button representation string
230+ local text = buttons_string (toolbar .buttons )
231+ local l_inset = 0
232+ if text :sub (1 , 1 ) == ' ' then
233+ -- don't overwrite the left border edge with a plain space
234+ l_inset = 1
235+ text = text :sub (2 )
236+ end
237+ self .label .frame .l = l_inset
238+ self .label :setText (text )
239+
240+ -- track actual toolbar, but with a y offset
241+ self .computeFrame = get_computeFrame_fn (toolbar , dy )
242+
243+ return self
244+ end
245+
246+ local left_toolbar_demo = ToolbarDemo {
148247 frame_title = ' left toolbar' ,
149- subviews = { widgets .Label { view_id = ' buttons' , frame = { l = 0 , r = 0 } } },
248+ toolbar = layout .fort .toolbars .left ,
249+ toolbar_dy = primary_toolbar_dy ,
150250}
151- local center_toolbar_demo = FortToolbarDemoPanel {
251+
252+ local center_toolbar_demo = ToolbarDemo {
152253 frame_title = ' center toolbar' ,
153- subviews = { widgets .Label { view_id = ' buttons' , frame = { l = 0 , r = 0 } } },
254+ toolbar = layout .fort .toolbars .center ,
255+ toolbar_dy = primary_toolbar_dy ,
154256}
155- local right_toolbar_demo = FortToolbarDemoPanel {
257+
258+ local right_toolbar_demo = ToolbarDemo {
156259 frame_title = ' right toolbar' ,
157- subviews = { widgets .Label { view_id = ' buttons' , frame = { l = 0 , r = 0 } } },
260+ toolbar = layout .fort .toolbars .right ,
261+ toolbar_dy = primary_toolbar_dy ,
158262}
159- local secondary_visible = false
160- local secondary_toolbar_demo = FortToolbarDemoPanel {
263+
264+ local secondary_toolbar_demo = ToolbarDemo {
161265 frame_title = ' secondary toolbar' ,
162- subviews = { widgets .Label { view_id = ' buttons' , frame = { l = 0 , r = 0 } } },
163- visible = function () return fort_toolbars_visible () and secondary_visible end ,
266+ visible = function ()
267+ return fort_toolbars_visible () and secondary_visible
268+ end ,
164269}
165270
166271fort_toolbars_demo .views = {
@@ -172,59 +277,26 @@ fort_toolbars_demo.views = {
172277
173278--- @param secondary ? DFLayout.Fort.SecondaryToolbar.Names
174279local function update_fort_toolbars (secondary )
175- -- by default, draw primary toolbar demonstrations right above the primary toolbars:
176- -- {l demo} {c demo} {r demo}
177- -- [l tool] [c tool] [r tool] (bottom of UI)
178- local toolbar_demo_dy = - layout .TOOLBAR_HEIGHT
179- local ir = gui .get_interface_rect ()
180- --- @param v widgets.Panel
181- --- @param frame widgets.Widget.frame
182- --- @param buttons DFLayout.Toolbar.NamedButtons
183- local function update (v , frame , buttons )
184- v .frame = {
185- w = frame .w ,
186- h = frame .h ,
187- l = frame .l + ir .x1 ,
188- t = frame .t + ir .y1 + toolbar_demo_dy ,
189- }
190- local sorted = {}
191- for _ , button in pairs (buttons ) do
192- utils .insert_sorted (sorted , button , ' offset' )
193- end
194- local buttons = ' '
195- for i , o in ipairs (sorted ) do
196- if o .offset > # buttons then
197- buttons = buttons .. (' ' ):rep (o .offset - # buttons )
198- end
199- if o .width == 1 then
200- buttons = buttons .. ' |'
201- elseif o .width > 1 then
202- buttons = buttons .. ' /' .. (' -' ):rep (o .width - 2 ) .. ' \\ '
203- end
280+ local function updateLayout (view )
281+ if view .frame_parent_rect then
282+ view :updateLayout ()
204283 end
205- v .subviews .buttons :setText (
206- buttons :sub (2 ) -- the demo panel border is at offset 0, so trim first character to start at offset 1
207- )
208- v :updateLayout ()
209284 end
210285 if secondary then
211- -- a secondary toolbar is active, move the primary demonstration up to
212- -- let the secondary be demonstrated right above the actual secondary:
213- -- {l demo} {c demo} {r demo}
214- -- {s demo}
215- -- [s tool]
216- -- [l tool] [c tool] [r tool] (bottom of UI)
217- update (secondary_toolbar_demo , layout .fort .secondary_toolbars [secondary ].frame (ir ),
218- layout .fort .secondary_toolbars [secondary ].buttons )
286+ -- show secondary demo just above actual secondary
287+ local function dy ()
288+ return - layout .SECONDARY_TOOLBAR_HEIGHT
289+ end
290+ secondary_toolbar_demo :update_to_toolbar (layout .fort .secondary_toolbars [secondary ], dy )
291+ updateLayout (secondary_toolbar_demo )
219292 secondary_visible = true
220- toolbar_demo_dy = toolbar_demo_dy - 2 * layout .SECONDARY_TOOLBAR_HEIGHT
221293 else
222294 secondary_visible = false
223295 end
224296
225- update (left_toolbar_demo , layout . fort . toolbars . left . frame ( ir ), layout . fort . toolbars . left . buttons )
226- update (right_toolbar_demo , layout . fort . toolbars . right . frame ( ir ), layout . fort . toolbars . right . buttons )
227- update (center_toolbar_demo , layout . fort . toolbars . center . frame ( ir ), layout . fort . toolbars . center . buttons )
297+ updateLayout (left_toolbar_demo )
298+ updateLayout (right_toolbar_demo )
299+ updateLayout (center_toolbar_demo )
228300end
229301
230302local tool_from_designation = {
@@ -303,13 +375,14 @@ fort_toolbars_demo.update = function()
303375end
304376
305377local secondary
378+ local center_render = center_toolbar_demo .render
306379function center_toolbar_demo :render (...)
307380 local new_secondary = active_secondary ()
308381 if new_secondary ~= secondary then
309382 secondary = new_secondary
310383 update_fort_toolbars (secondary )
311384 end
312- return FortToolbarDemoPanel . render (self , ... )
385+ return center_render (self , ... )
313386end
314387
315388--- start demo control window ---
0 commit comments