|
| 1 | +function plugindef() |
| 2 | + finaleplugin.RequireSelection = true |
| 3 | + finaleplugin.Author = "Jacob Winkler, Nick Mazuk & Carl Vine" |
| 4 | + finaleplugin. AuthorEmail = "[email protected]" |
| 5 | + finaleplugin.Copyright = "CC0 https://creativecommons.org/publicdomain/zero/1.0/" |
| 6 | + finaleplugin.Version = "1.0" |
| 7 | + finaleplugin.Date = "2024-01-26" |
| 8 | + finaleplugin.CategoryTags = "Pitch" |
| 9 | + finaleplugin.Notes = [[ |
| 10 | +USING PITCH ENTRY KEEP-DELETE |
| 11 | +
|
| 12 | +Select a note within each chord to either keep or delete, |
| 13 | +numbered from either the top or bottom of each chord. |
| 14 | +"1" deletes (or keeps) the top (or bottom) note, |
| 15 | +"2" deletes (or keeps) the 2nd note from top (or from bottom), |
| 16 | +etc. |
| 17 | +
|
| 18 | +== Key Commands == |
| 19 | +• [a] keep |
| 20 | +• [z] delete |
| 21 | +• [s] from the top |
| 22 | +• [x] from the bottom |
| 23 | +• [q] toggle keep/delete |
| 24 | +• [w] toggle top/bottom |
| 25 | +• [1-9] enter note count (delete key not needed) |
| 26 | +]] |
| 27 | + return "Pitch: Chord Notes Keep-Delete...", "Pitch: Chord Notes Keep-Delete", |
| 28 | + "Keep or Delete selected notes from chords" |
| 29 | +end |
| 30 | + |
| 31 | +local configuration = require("library.configuration") |
| 32 | +local note_entry = require("library.note_entry") |
| 33 | +local mixin = require("library.mixin") |
| 34 | +local library = require("library.general_library") |
| 35 | +local script_name = library.calc_script_name() |
| 36 | + |
| 37 | +local config = { -- retained and over-written by the user's "settings" file |
| 38 | + number = 1, -- which note to work on |
| 39 | + direction = 0, -- 0 == from top / 1 == from bottom |
| 40 | + keep_delete = 0, -- 0 == keep / 1 == delete |
| 41 | + window_pos_x = false, |
| 42 | + window_pos_y = false, |
| 43 | +} |
| 44 | + |
| 45 | +local function dialog_set_position(dialog) |
| 46 | + if config.window_pos_x and config.window_pos_y then |
| 47 | + dialog:StorePosition() |
| 48 | + dialog:SetRestorePositionOnlyData(config.window_pos_x, config.window_pos_y) |
| 49 | + dialog:RestorePosition() |
| 50 | + end |
| 51 | +end |
| 52 | + |
| 53 | +local function dialog_save_position(dialog) |
| 54 | + dialog:StorePosition() |
| 55 | + config.window_pos_x = dialog.StoredX |
| 56 | + config.window_pos_y = dialog.StoredY |
| 57 | + configuration.save_user_settings(script_name, config) |
| 58 | +end |
| 59 | + |
| 60 | +local function user_chooses() |
| 61 | + local x, y, y_diff = 85, 3, 20 |
| 62 | + local y_offset = finenv.UI():IsOnMac() and 3 or 0 |
| 63 | + local answer = {} |
| 64 | + local saved = config.number |
| 65 | + -- |
| 66 | + local function flip_popup(name) |
| 67 | + local n = answer[name]:GetSelectedItem() |
| 68 | + answer[name]:SetSelectedItem((n + 1) % 2) |
| 69 | + end |
| 70 | + local function key_check(ctl) |
| 71 | + local s = ctl:GetText():lower() |
| 72 | + if s:find("[^0-9]") then |
| 73 | + if s:find("a") then answer.keep_delete:SetSelectedItem(0) |
| 74 | + elseif s:find("z") then answer.keep_delete:SetSelectedItem(1) |
| 75 | + elseif s:find("q") then flip_popup("keep_delete") |
| 76 | + elseif s:find("s") then answer.direction:SetSelectedItem(0) |
| 77 | + elseif s:find("x") then answer.direction:SetSelectedItem(1) |
| 78 | + elseif s:find("w") then flip_popup("direction") |
| 79 | + end |
| 80 | + ctl:SetText(saved):SetKeyboardFocus() |
| 81 | + elseif s ~= "" then |
| 82 | + s = s:sub(-1) -- 1-digit note number |
| 83 | + ctl:SetText(s) |
| 84 | + saved = s |
| 85 | + end |
| 86 | + end |
| 87 | + -- |
| 88 | + local dialog = mixin.FCXCustomLuaWindow():SetTitle(plugindef():gsub("%.%.%.", "")) |
| 89 | + dialog:CreateStatic(0, y):SetText("Note Number:"):SetWidth(x) |
| 90 | + answer.number = dialog:CreateEdit(x, y - y_offset):SetInteger(config.number) |
| 91 | + :AddHandleCommand(function(self) key_check(self) end):SetWidth(25) |
| 92 | + y = y + y_diff |
| 93 | + answer.keep_delete = dialog:CreatePopup(0, y):SetWidth(x - 10) |
| 94 | + :AddStrings("Keep (a)", "Delete (z)") -- == 0 ... 1 |
| 95 | + :SetSelectedItem(config.keep_delete) |
| 96 | + answer.direction = dialog:CreatePopup(x, y):SetWidth(110) |
| 97 | + :AddStrings("From Top (s)", "From Bottom (x)") -- == 0 ... 1 |
| 98 | + :SetSelectedItem(config.direction) |
| 99 | + |
| 100 | + dialog:CreateOkButton() |
| 101 | + dialog:CreateCancelButton() |
| 102 | + dialog_set_position(dialog) |
| 103 | + dialog:RegisterHandleOkButtonPressed(function() |
| 104 | + config.number = answer.number:GetInteger() |
| 105 | + config.direction = answer.direction:GetSelectedItem() |
| 106 | + config.keep_delete = answer.keep_delete:GetSelectedItem() |
| 107 | + end) |
| 108 | + dialog:RegisterInitWindow(function() answer.number:SetKeyboardFocus() end) |
| 109 | + dialog:RegisterCloseWindow(function(self) dialog_save_position(self) end) |
| 110 | + return (dialog:ExecuteModal() == finale.EXECMODAL_OK) |
| 111 | +end |
| 112 | + |
| 113 | +local function keep_delete() |
| 114 | + configuration.get_user_settings(script_name, config, true) |
| 115 | + if not user_chooses() then return end -- user cancelled |
| 116 | + |
| 117 | + for entry in eachentrysaved(finenv.Region()) do |
| 118 | + if (entry.Count >= 2) then |
| 119 | + local n = math.max(config.number, 1) |
| 120 | + local target = (config.direction == 0) and (n - 1) or (entry.Count - n) |
| 121 | + local i = 0 |
| 122 | + for note in eachbackwards(entry) do |
| 123 | + if (i == target and config.keep_delete == 1) |
| 124 | + or (i ~= target and config.keep_delete == 0) then |
| 125 | + note_entry.delete_note(note) |
| 126 | + end |
| 127 | + i = i + 1 |
| 128 | + end |
| 129 | + end |
| 130 | + end |
| 131 | +end |
| 132 | + |
| 133 | +keep_delete() |
0 commit comments