route bank_panel bank-op persists through persistBankOp so panel gestures get undo points like the bindable actions

This commit is contained in:
2026-07-26 15:25:15 -04:00
parent 3f3ee94e77
commit 3514bb0b6d
3 changed files with 71 additions and 25 deletions
+29 -9
View File
@@ -46,6 +46,7 @@
#include <unordered_map>
#include <vector>
#include "actions.h" // persistBankOp — shared undo-block wrapper (R-B panel path)
#include "bank_book.h"
#include "bank_grid.h"
#include "bank_model.h"
@@ -1224,7 +1225,7 @@ void doCreateBank() {
}
g_panel.shownBankId = id; // show the freshly-created bank
g_panel.focusedRegion = Region::Banks;
persistBook();
persistBankOp("ReaSampler: create bank");
invalidatePanel();
}
@@ -1240,7 +1241,7 @@ void doRenameBank(const std::string& bankId) {
"ReaSampler: rename bank", 0);
return;
}
persistBook();
persistBankOp("ReaSampler: rename bank");
invalidatePanel();
}
@@ -1273,7 +1274,7 @@ void doDeleteBank(const std::string& bankId) {
// r == 6 (Yes) falls through to a plain delete (drops members).
}
if (!book()->deleteBank(bankId)) return;
persistBook();
persistBankOp("ReaSampler: delete bank");
// shownBankId is reconciled by the next fingerprint pass. If no named banks remain,
// nudge focus to the pool so the selection has a valid home.
if (namedBanks().empty()) g_panel.focusedRegion = Region::Pool;
@@ -1285,30 +1286,49 @@ void doEvacuateBank(const std::string& bankId) {
const Bank* bk = book()->bank(bankId);
if (!bk || bk->isPool()) return;
if (!book()->evacuate(bankId)) return;
persistBook();
persistBankOp("ReaSampler: evacuate bank");
invalidatePanel();
}
void doActivateBank(const std::string& bankId) {
if (!book()) return;
if (!book()->setActiveBank(bankId)) return; // rejects an unknown id
persistBook();
persistBankOp("ReaSampler: activate bank");
invalidatePanel();
}
// Move or copy `sampleIds` from `srcBankId` to `destBankId` (index-only). Both pass
// ids straight to the model op (no BankIndex& cached across the loop's mutations).
//
// NO-OP GUARDRAIL — VERB-AWARE (matches the action layer's doBankTransferSelected):
// * MOVE collapse: the source entry WAS removed (bank_book removes unconditionally
// before the dest add collapses on hash), so the index DID mutate — counts.
// * COPY collapse: the source is left intact AND the dest already held the hash,
// so NOTHING changed — a true index no-op. Must NOT open an undo point.
// Hence: copy counts only real gains (Copied); move counts gains OR collapses.
void transferSamples(const std::vector<std::string>& sampleIds,
const std::string& srcBankId, const std::string& destBankId,
bool copy) {
if (!book()) return;
if (sampleIds.empty() || srcBankId == destBankId) return;
if (!book()->bank(srcBankId) || !book()->bank(destBankId)) return;
int ok = 0, collapsed = 0;
for (const std::string& sid : sampleIds) {
if (copy) book()->copySample(sid, srcBankId, destBankId);
else book()->moveSample(sid, srcBankId, destBankId);
const TransferResult r =
copy ? book()->copySample(sid, srcBankId, destBankId)
: book()->moveSample(sid, srcBankId, destBankId);
switch (r) {
case TransferResult::Moved:
case TransferResult::Copied: ++ok; break;
case TransferResult::Collapsed: ++collapsed; break;
default: break;
}
}
persistBook();
const bool mutated = copy ? (ok > 0) : (ok > 0 || collapsed > 0);
if (!mutated) return; // nothing changed — no persist, no undo point
const char* label = copy ? "ReaSampler: copy sample(s)" : "ReaSampler: move sample(s)";
persistBankOp(label);
// The selection indexed into the source; after a move those indices are stale, so
// clear it (the fingerprint pass will also clear, but do it now for immediacy).
g_panel.selection = Selection{};
@@ -1357,7 +1377,7 @@ void removeSamples(const std::vector<std::string>& sampleIds,
++removed;
if (removed == 0) return; // nothing changed — no persist, no undo point
persistBook();
persistBankOp("ReaSampler: remove sample(s)");
// The selection indexed into the source; after a remove those indices are stale, so
// clear it (the fingerprint pass will also clear, but do it now for immediacy).
g_panel.selection = Selection{};