@@ -4,8 +4,8 @@ function plugindef()
44 finaleplugin .Author = " Carl Vine"
55 finaleplugin .AuthorURL = " https://carlvine.com/lua/"
66 finaleplugin .Copyright = " https://creativecommons.org/licenses/by/4.0/"
7- finaleplugin .Version = " 0.95i "
8- finaleplugin .Date = " 2024/05/22 "
7+ finaleplugin .Version = " 0.95k "
8+ finaleplugin .Date = " 2024/07/23 "
99 finaleplugin .MinJWLuaVersion = 0.74
1010 finaleplugin .ScriptGroupDescription = " Selected notes are cross-staffed to the next staff above or below"
1111 finaleplugin .Notes = [[
@@ -16,10 +16,10 @@ function plugindef()
1616 stem reversal, horizontal note shift (to counteract stem reversal),
1717 note pattern matching and beam height adjustment.
1818
19- Hold [Shift ] when starting the script to quickly cross staves
19+ Hold [_Shift_ ] when starting the script to quickly cross staves
2020 without a confirmation dialog, with the settings last used.
2121 Select __Modeless Dialog__ if you want the dialog window to persist
22- on-screen for repeated use until you click _Cancel_ [Escape ].
22+ on-screen for repeated use until you click __Close__ [_Escape_ ].
2323
2424 __Reverse Stems For Mid-Staff Beams__
2525 To centre beams _between_ the staves, the stems of __Crossed__
@@ -64,7 +64,7 @@ local units = { -- map keystrokes onto Measurement Unit ENUMs
6464 c = finale .MEASUREMENTUNIT_CENTIMETERS , o = finale .MEASUREMENTUNIT_POINTS ,
6565 a = finale .MEASUREMENTUNIT_PICAS , s = finale .MEASUREMENTUNIT_SPACES ,
6666}
67- local hotkey = { -- customise Key Commands (lower case only)
67+ local hotkey = { -- customise Key Commands (lowercase only)
6868 rest_fill = " d" ,
6969 not_unbeamed = " f" ,
7070 reversing = " g" ,
@@ -75,26 +75,26 @@ local hotkey = { -- customise Key Commands (lower case only)
7575 modeless = " m" ,
7676 script_info = " q" ,
7777 -- optionally re-map MEASUREMENTUNIT hotkeys:
78- e = " e" ,
79- i = " i" ,
80- c = " c" ,
81- o = " o" ,
82- a = " a" ,
83- s = " s" ,
78+ e = " e" ,
79+ i = " i" ,
80+ c = " c" ,
81+ o = " o" ,
82+ a = " a" ,
83+ s = " s" ,
8484}
8585local config = {
8686 rest_fill = true , -- fill destination with invisible rest
8787 not_unbeamed = true , -- true to prevent unbeamed notes
8888 reversing = true , -- true to allow reversing cross-note stems
8989 whole_measure = false , -- horizontal shift across whole measure
90- measurement_unit = finale .MEASUREMENTUNIT_DEFAULT ,
91- layer_num = 0 ,
92- direction = " Up" , -- (or "Down")
90+ direction = " Up" , -- (or "Down")
9391 modeless = false ,
92+ layer_num = 0 ,
9493 count_notes = 1 , -- "Cross" x notes
9594 count_out_of = 1 , -- "out of" y notes
9695 window_pos_x = false ,
9796 window_pos_y = false ,
97+ measurement_unit = finale .MEASUREMENTUNIT_DEFAULT ,
9898}
9999
100100local offsets = { -- (ordered) name; default value; text description; h_offset
@@ -144,7 +144,8 @@ local function get_staff_name(staff_num)
144144 return str
145145end
146146
147- local function next_staff_or_error (rgn , dialog )
147+ local function next_staff_or_error (dialog )
148+ local rgn = finenv .Region ()
148149 local msg = " "
149150 local stack = mixin .FCMMusicRegion ()
150151 stack :SetRegion (rgn ):SetFullMeasureStack ()
@@ -168,11 +169,8 @@ local function next_staff_or_error(rgn, dialog)
168169 end
169170 end
170171 if msg ~= " " then -- **ERROR**
171- if dialog then
172- dialog :CreateChildUI ():AlertError (msg , name .. " : Error" )
173- else
174- finenv .UI ():AlertError (msg , name .. " : Error" )
175- end
172+ local ui = dialog and dialog :CreateChildUI () or finenv .UI ()
173+ ui :AlertError (msg , name .. " : Error" )
176174 return - 1 -- flag error
177175 end
178176 return stack :CalcStaffNumber (next_slot )
197195
198196local function clean_entry (entry ) -- erase pre-exisiting conditions
199197 if entry :IsNote () then
200- for i = 1 , entry . Count do
201- finale .FCCrossStaffMod ():EraseAt (entry : GetItemAt ( i - 1 ) )
198+ for note in each ( entry ) do
199+ finale .FCCrossStaffMod ():EraseAt (note )
202200 end
203201 local mods = finale .FCCrossStaffMods (entry )
204202 mods :LoadAll ()
@@ -224,12 +222,12 @@ local function destination_rests(rgn, dest_staff_num)
224222 note_cell :Load ()
225223 if note_cell .Count == 0 then -- destination empty so proceed
226224 local m = finale .FCMeasure ()
227- local m_duration = m :Load (measure_num ) and m :GetDuration () or finale .WHOLE_NOTE
225+ local duration = m :Load (measure_num ) and m :GetDuration () or finale .WHOLE_NOTE
228226 local new_rest = note_cell :AppendEntriesInLayer (layer_num , 1 )
229227 if new_rest then
230- new_rest :MakeRest ():SetDuration (m_duration ):SetLegality (true ):SetVisible (false )
228+ new_rest :MakeRest ():SetDuration (duration ):SetLegality (true ):SetVisible (false )
231229 note_cell :Save ()
232- end
230+ end
233231 end
234232 end
235233end
@@ -304,7 +302,7 @@ local function cross_staff(dialog)
304302 local rgn = mixin .FCMMusicRegion ()
305303 rgn :SetRegion (finenv .Region ())
306304
307- local next_staff = next_staff_or_error (rgn , dialog )
305+ local next_staff = next_staff_or_error (dialog )
308306 if next_staff < 0 then return false end -- error finding "next staff"
309307 -- ready to cross staves
310308 finenv .StartNewUndoBlock (string.format (" Cross-Staff %s -> %s m.%d" ,
@@ -363,7 +361,6 @@ local function cross_staff(dialog)
363361 end
364362 finale .FCNoteEntry .MarkEntryMetricsForUpdate ()
365363 end
366-
367364 -- pass 4 (measure) stem reversal & crossing
368365 bsen = nil
369366 for entry in eachentrysaved (whole_measure , config .layer_num ) do
@@ -382,8 +379,8 @@ local function cross_staff(dialog)
382379 end
383380 end
384381 end
385- bsen = nil
386382 -- pass 5 (measure) shift beam if "mixed" crossed-and-uncrossed
383+ bsen = nil
387384 for entry in eachentrysaved (whole_measure , config .layer_num ) do
388385 if entry :IsNote () then
389386 local enum = entry .EntryNumber
447444
448445local function run_the_dialog ()
449446 local max = layer .max_layers ()
450- local x = { 140 , 210 , 245 }
447+ local x = { 140 , 210 , 245 }
451448 local y = 0
452449 local answer , save_value = {}, {} -- "Edit" controls / saved "text" values
453450 local dialog = mixin .FCXCustomLuaWindow ():SetTitle (name )
@@ -458,19 +455,31 @@ local function run_the_dialog()
458455 refocus_document = true
459456 end
460457 local function dy (diff )
461- y = diff and ( y + diff ) or ( y + 25 )
458+ y = y + ( diff or 25 )
462459 end
463460 local function cstat (cx , cy , ctext , cwide )
464- local stat = dialog :CreateStatic (cx , cy ):SetText (ctext )
465- if cwide then stat :SetWidth (cwide ) end
466- return stat
461+ local s = dialog :CreateStatic (cx , cy ):SetText (ctext )
462+ if cwide then s :SetWidth (cwide ) end
463+ return s
464+ end
465+ local function offset_enable_status ()
466+ local up = answer .direction :GetSelectedItem () -- 0 = "Up", 1 = "Down"
467+ local status = (answer .reversing :GetCheck () == 1 ) -- "reversing" = true
468+ for i = 0 , 1 do -- check "Up" then "Down" values
469+ local enable = status and (i == up )
470+ -- enable/disable matching "Offset" labels, "off1"/"off3"
471+ answer [" off" .. i * 2 + 1 ]:SetEnable (enable )
472+ for j = 1 , 2 do
473+ answer [offsets [i * 2 + j ][1 ]]:SetEnable (enable )
474+ end
475+ end
467476 end
468477 local function set_offset_disable ()
469- local enable = answer .reversing :GetCheck () == 1
470- for i = 1 , 4 do answer [offsets [i ][1 ]]:SetEnable (enable ) end
471- for _ , v in ipairs {" whole_measure" , " h1" , " h2" , " h3" , " off1" , " off3" } do
472- answer [v ]:SetEnable (enable )
478+ local status = (answer .reversing :GetCheck () == 1 ) -- "reversing" = true
479+ for _ , v in ipairs {" whole_measure" , " h0" , " h1" , " h2" , " zero" , " default" } do
480+ answer [v ]:SetEnable (status )
473481 end
482+ offset_enable_status ()
474483 answer [pattern [1 ][1 ]]:SetKeyboardFocus ()
475484 end
476485 local function update_saved ()
@@ -509,11 +518,14 @@ local function run_the_dialog()
509518 elseif s :find (hotkey .direction ) then
510519 local n = answer .direction :GetSelectedItem ()
511520 answer .direction :SetSelectedItem ((n + 1 ) % 2 )
521+ offset_enable_status ()
512522 else -- remaining simple checkboxes
513523 for k , v in pairs (hotkey ) do
514524 if s :find (v ) then
515525 answer [k ]:SetCheck ((answer [k ]:GetCheck () + 1 ) % 2 )
516- if k == " reversing" then set_offset_disable () end
526+ if k == " reversing" then set_offset_disable ()
527+ else answer [k ]:SetCheck ((answer [k ]:GetCheck () + 1 ) % 2 )
528+ end
517529 break
518530 end
519531 end
@@ -538,8 +550,9 @@ local function run_the_dialog()
538550 answer .direction = dialog :CreatePopup (0 , y - 1 ):SetWidth (90 )
539551 :AddStrings (" Cross Up" , " Cross Down" ) -- item# == 0 or 1
540552 :SetSelectedItem (config .direction == " Up" and 0 or 1 )
553+ :AddHandleCommand (function () offset_enable_status () end )
541554 answer .modeless = dialog :CreateCheckbox (131 , y ):SetWidth (120 )
542- :SetCheck (config .modeless and 1 or 0 ):SetText (" \" Modeless\" Dialog" )
555+ :SetCheck (config .modeless and 1 or 0 ):SetText (" Modeless Dialog" )
543556 answer .q = dialog :CreateButton (x [2 ] + 44 , y ):SetText (" ?" ):SetWidth (20 )
544557 :AddHandleCommand (function () show_info () end )
545558 dy ()
@@ -569,16 +582,17 @@ local function run_the_dialog()
569582 dy (8 )
570583 dialog :CreateHorizontalLine (0 , y - 5 , x [2 ] + 64 )
571584 dialog :CreateHorizontalLine (0 , y - 4 , x [2 ] + 64 )
572- answer .h1 = cstat (x [1 ] + 4 , y + 2 , " HORIZONTAL OFFSETS" , 130 )
585+ answer .h0 = cstat (x [1 ] + 4 , y + 2 , " HORIZONTAL OFFSETS" , 130 )
573586 dy (12 )
574587 cstat (0 , y - 7 , " Units:" , 37 )
575588 answer .popup = dialog :CreateMeasurementUnitPopup (37 , y - 8 ):SetWidth (90 )
576589 :AddHandleCommand (function () update_saved () end )
577- answer .h2 = cstat (x [1 ], y + 2 , " Crossed" , 70 )
578- answer .h3 = cstat (x [2 ] - 4 , y + 2 , " Not Crossed" , 70 )
590+ answer .h1 = cstat (x [1 ], y + 2 , " Crossed" , 70 )
591+ answer .h2 = cstat (x [2 ] - 4 , y + 2 , " Not Crossed" , 70 )
579592
580593 for i , v in ipairs (offsets ) do -- OFFSET MEASUREMENTS
581594 if (i % 2 == 1 ) then dy (20 ) end
595+ if i == 5 then dy (25 ) end -- "beam vertical" sits BELOW the "Horiz" buttons
582596 answer [v [1 ]] = dialog :CreateMeasurementEdit ((i % 2 == 1 ) and x [1 ] or x [2 ], y - y_off )
583597 :SetMeasurementInteger (config [v [1 ]]):SetWidth (63 )
584598 :AddHandleCommand (function () key_check (v [1 ]) end )
@@ -588,21 +602,20 @@ local function run_the_dialog()
588602 end
589603 -- set "saved" edit values
590604 update_saved ()
591- dy (20 )
592- dialog :CreateButton (x [1 ], y ):SetWidth (105 )
593- :SetText (" Zero Horiz. (" .. hotkey .set_zero .. " )" )
594- :AddHandleCommand (function () set_default_values (0 ) end )
595- dialog :CreateButton (20 , y ):SetWidth (105 )
605+ dy (- 23 ) -- move back ABOVE the "beam vertical" box
606+ answer .default = dialog :CreateButton (20 , y ):SetWidth (105 )
596607 :SetText (" Default Horiz. (" .. hotkey .set_default .. " )" )
597608 :AddHandleCommand (function () set_default_values () end )
598-
599- dialog :CreateOkButton ():SetText (config .modeless and " Apply" or " OK" )
600- dialog :CreateCancelButton ()
609+ answer .zero = dialog :CreateButton (x [1 ], y ):SetWidth (105 )
610+ :SetText (" Zero Horiz. (" .. hotkey .set_zero .. " )" )
611+ :AddHandleCommand (function () set_default_values (0 ) end )
612+ --
613+ dialog :CreateOkButton () :SetText (config .modeless and " Apply" or " OK" )
614+ dialog :CreateCancelButton ():SetText (config .modeless and " Close" or " Cancel" )
601615 dialog_set_position (dialog )
602616 local change_mode , user_error = false , false
603- dialog :RegisterInitWindow (function (self )
617+ dialog :RegisterInitWindow (function ()
604618 set_offset_disable ()
605- self :SetOkButtonCanClose (not config .modeless )
606619 answer .q :SetFont (answer .q :CreateFontInfo ():SetBold (true ))
607620 end )
608621 dialog :RegisterHandleOkButtonPressed (function (self )
0 commit comments